|
Thread Rules 1. This is not a "do my homework for me" thread. If you have specific questions, ask, but don't post an assignment or homework problem and expect an exact solution. 2. No recruiting for your cockamamie projects (you won't replace facebook with 3 dudes you found on the internet and $20) 3. If you can't articulate why a language is bad, don't start slinging shit about it. Just remember that nothing is worse than making CSS IE6 compatible. 4. Use [code] tags to format code blocks. |
On September 16 2013 06:05 spinesheath wrote: By the way, is "Code Complete" the book where the author says about checked exceptions that "the discussion is over"? Because that sure is a debatable statement (even though there are no satisfying implementations of the concept in popular languages). No, that's Clean Code.
|
On September 16 2013 07:59 darkness wrote: Well, I didn't think much like a programmer in year 1. index[1] is more natural to humans than index[0] imho, so my approach was like that back then. I don't do it anymore though. It happened only once anyway.
I am surprised that a book recommended by universities suggests ignoring the 0 index.
I believe they only suggested it for this particular case (days/months). Still it was a very ugly solution.
|
It is relatively uncommon to "waste time" correcting an unmanageable number of compile errors caused by a change in the return type of a getter or setter. At least if you don't already have a massive problem of domain objects being overexposed within the codebase, etc. Getters and setters offer a realistic way of enforcing design contracts. What that article is essentially recommending is that you should instead be proper and add code to your domain objects that would make them aware of outside implementation details. The author's suggestion that you "just use a Facade" just abstracts away the amount of boilerplate required to achieve something relatively simple. In a production environment you'll find that boilerplate has the potential to be more problematic than a real or imagined lack of object orientation. At a certain point you have to ask yourself if you're writing code to solve a problem or so that you can stand on your chair and scream CYRAX WINS: ANALITY.
|
On September 16 2013 10:04 lolmlg wrote:It is relatively uncommon to "waste time" correcting an unmanageable number of compile errors caused by a change in the return type of a getter or setter. At least if you don't already have a massive problem of domain objects being overexposed within the codebase, etc. Getters and setters offer a realistic way of enforcing design contracts. What that article is essentially recommending is that you should instead be proper and add code to your domain objects that would make them aware of outside implementation details. The author's suggestion that you "just use a Facade" just abstracts away the amount of boilerplate required to achieve something relatively simple. In a production environment you'll find that boilerplate has the potential to be more problematic than a real or imagined lack of object orientation. At a certain point you have to ask yourself if you're writing code to solve a problem or so that you can stand on your chair and scream CYRAX WINS: ANALITY.
On a more academic level, though, I would love to hear what other people think about this. It's always seemed a little at odds to me that in most C++ classes you're taught all about how you should try to 'hide the implementation of a class' as much as possible, but then they also tell you to add getters and setters to all of your classes. The example is given sometimes (like in that article!) that if you have public member variables, then you change the type of one of those member variables, then all the code that uses that variable has to be changed (either to cast it to the proper type, or deal with it some other way) - so you should make those variables private. But isn't that also an issue when you have get/set methods for your classes, if people are using those methods indiscriminately? Doesn't it just in essence provide all of the same problems wrapped in an extra layer of complexity?
e:clarity
e2: to quote the article linked: A fundamental precept of OO systems is that an object should not expose any of its implementation details. This way, you can change the implementation without changing the code that uses the object. It follows then that in OO systems you should avoid getter and setter functions since they mostly provide access to implementation details.
Basically I guess my question is, does that not make total sense to anyone else? And if it does, why do all of my university OOP courses recommend adding get/set methods to my classes?
|
On September 16 2013 12:00 Cyx. wrote:Show nested quote +On September 16 2013 10:04 lolmlg wrote:It is relatively uncommon to "waste time" correcting an unmanageable number of compile errors caused by a change in the return type of a getter or setter. At least if you don't already have a massive problem of domain objects being overexposed within the codebase, etc. Getters and setters offer a realistic way of enforcing design contracts. What that article is essentially recommending is that you should instead be proper and add code to your domain objects that would make them aware of outside implementation details. The author's suggestion that you "just use a Facade" just abstracts away the amount of boilerplate required to achieve something relatively simple. In a production environment you'll find that boilerplate has the potential to be more problematic than a real or imagined lack of object orientation. At a certain point you have to ask yourself if you're writing code to solve a problem or so that you can stand on your chair and scream CYRAX WINS: ANALITY. On a more academic level, though, I would love to hear what other people think about this. It's always seemed a little at odds to me that in most C++ classes you're taught all about how you should try to 'hide the implementation of a class' as much as possible, but then they also tell you to add getters and setters to all of your classes. The example is given sometimes (like in that article!) that if you have public member variables, then you change the type of one of those member variables, then all the code that uses that variable has to be changed (either to cast it to the proper type, or deal with it some other way) - so you should make those variables private. But isn't that also an issue when you have get/set methods for your classes, if people are using those methods indiscriminately? Doesn't it just in essence provide all of the same problems wrapped in an extra layer of complexity? e:clarity e2: to quote the article linked: Show nested quote +A fundamental precept of OO systems is that an object should not expose any of its implementation details. This way, you can change the implementation without changing the code that uses the object. It follows then that in OO systems you should avoid getter and setter functions since they mostly provide access to implementation details. Basically I guess my question is, does that not make total sense to anyone else? And if it does, why do all of my university OOP courses recommend adding get/set methods to my classes? Probably either because they are taught by someone who doesn't understand OOD very well (many academics do not care, but are forced to teach it anyway as someone has to) or proper explanation is too advanced for an introductory class and hard to test (good OOP, especially in a practical setting is very hard to clearly explain).
Getters/setters are a bit better than nakedly exposing your members in that they allow you some flexibility, but they often still reflect implementation details way too much. You should never need to worry about setting or getting data that an object stores, an object has actions it can perform, not variables that can be set. To use a textbook style simplistic example in a class "computer" you should have a member function "turn_off()", not a "set_power_status(bool)". Even if power_status is initially just a boolean it may at some point become more complicated, especially when you consider inheritance.
Getters/Setters are like singletons in that they may have some very rare applications in an OO program, but their legitimate uses are very rare and usually they are just used to hide the fact that the program is not actually OO (or has globals in the case of a singleton).
Let me share an example where I thought a getter/setter might be useful and allow me flexibility in terms of my private representation of data, but it ended up tying the usage of my class way too tightly with my internal representation. I was writing a matrix class in C++ and the underlying storage was simply a dynamically allocated array of floats. I added public member functions: float* get_data(); void set_data(float* data_ptr); The first promised to return a pointer to an array of the data in row-first format which would not be free'd until the matrix object was destructed. The second copied that data in data_ptr to my internal storage before returning. I felt the need for these as certain third-party libraries just took a float pointer (in particular LAPACK and BLAS) and it seemed like I should allow users a way to use my matrix class with those libraries.
At some point I started working with large arrays and it turned out that when doing common operations I got poor performance due to how data was laid out in memory. Often I might need to access an element and the one just below it, but these were very far apart in memory which lead to atrocious performance. The trick I used was to lay out the data in memory by blocks so the first 4096 bytes of my array represented the top left 32 x 32 block of elements, and so on. However this meant that whenever anyone called get_data I would have to allocate a large float array (~1MB), copy all the data to it and keep track of it so I could delete it in the destructor. I did some caching to optimize, but it was still awfully slow.
It got so slow that I couldn't really use it so I declared get_data deprecated and set upon removing all references to it (this was always just my personal project, though I used it in projects that I considered making public). This meant I had to write my own functions to replace the parts of BLAS or LAPACK I was using (in particular I had to write several matrix factorization functions). However as the data grew I ran into another problem. Suddenly the data was so large that I could not allocate it in a contiguous chunk of memory. I was working with 50MB matrices and malloc could simply not handle that. Internally it was not a big problem as I had already gone on to represent my matrix internally by blocks so that was easily adapted to allocate in smaller chunks, but I had promised for get_data to return a contiguous chunk of memory and I simply couldn't deliver. Luckily I was only using this matrix class myself, so removing it was no problem, but in a production environment or public library it would have been a huge deal. The matrix class I currently use has a function: bool submatrix(float* ptr,int x1,int x2,int y1,int y2) const; which copies the submatrix of rows x1 to x2 and columns y1 to y2 into ptr. If it cannot do that for some reason, then it returns false. I also have a way to get access to the internal representation of submatrices since that is sometimes necessitated by practical performance concerns and third-party libraries, but I have left it a way to fail as the one above and I'm aware that it is not good OOD.
In practice there are times where you may want to simply do getters/setters or even have public data, or a global, but do not hide behind language features and pretend you are designing OO code.
That turned out longer than I had anticipated, sorry for the very verbose example.
|
Getters/Setters (or Properties in languages that support them like C#) are far better than public instance variables. If you change how the variable should be calculated, you're screwed if you access the variable directly from other classes, you have to rewrite them all. If you have a getter or setter, you can simply put the calculation in the getter or setter, and all the classes using it will get the right value without changing anything. The point being that a getter and setter should be something vital to the class which will always be important to other objects, and by putting it in a getter/setter, you can still change how that value is given to the other classes, making it safe for them to use it indiscriminately.
That said, like rasjn wrote, the problem is that other classes should preferably not be coupled so hard that they need access to the variables in the first place, they should create the object, make it do work, then get what they want from that work.
One of the situations where setters and getters / properties are good is if you have a class which does some pretty advanced actions which need a lot of initial setup. Instead of a mile long constructor with 30 parameters, you can force the user to create it and then set it up using getter/setter/properties.
As long as your initial interface to the class is well thought out, it shouldn't be an issue, because you will know ahead of time exactly what methods and properties are "core" to the class, and other objects will always need access to those, and it's no problem to make getters and setters for those (though giving access to variables directly is a bad idea regardless). For example, if you make a Connection class which works with a database, this class will always need to have a connection string. You could be a "perfectionist" and say that the connectionstring is supplied in the constructor and that's it, but chances are you at least want a getter for it, and in that case you have a connection class with a connectionstring getter... and it's not like it's likely that you will ever want to get rid of that getter.
|
On September 16 2013 08:48 ShAsTa wrote:Show nested quote +On September 16 2013 06:05 spinesheath wrote: By the way, is "Code Complete" the book where the author says about checked exceptions that "the discussion is over"? Because that sure is a debatable statement (even though there are no satisfying implementations of the concept in popular languages). No, that's Clean Code. I knew it was one of the two :p
Getters\setters aren't bad, bad interface design is bad. If you design a proper interface and there are certain values that you want accessible through the interface (simple example: the size of a list/stack), then there should be a getter for that. How the size is calculated behind the scenes (just return a variable or do some math) is hidden, while the access, which is part of the interface, is public.
Do not add random getters/setters to your classes just because you have some class variables. Always think in terms of interfaces.
|
Speaking of getters and setters, it may be nice if Java supported their auto generation like in Objective C.
|
Getters and setters are actually a very complicated topic. On the first look, it often doesn't make a difference because the code looks like this:
class X { private String someString = ""; public String getSomeString() { return this->someString; } public String setSomeString(String newString) { this->someString = newString; } }
Yes, it looks like the getters and setters are superfluous and direct access to the variable is always better. It usually isn't.
Let's take an example: You are writing a program for human resources where they can manage employees, etc. Their old program uses just a single full name field for employees, so in the beginning you write your program to do the same:
class Employee { private String fullName = "Doe, John"; public String getFullName() { return this->fullName; } public String setFullName(String newName) { this->fullName = newName; } }
After a year or so of using it, the company buys a new accounting or whatever application that requires the name as firstname and lastname seperately through their API. However, you still have lots of places where you show the full name in the application and the HR people like it that way, so you only change the underlying implementation and the places where data is entered, not where it is read:
class Employee { private String firstName = "John"; private String lastName = "Doe"; public String getFullName() { return this->lastName + ", " + this->firstName; } public String setFirstName(...) { ... } public String setLastName(...) { ... } public String getFirstName() { ... } public String getLastName() { ... }
// Deprecated public String setFullName(String newName) { String[] names = newName.split(', '); this->setLastName(names[0]); this->setFirstName(names[1]); } }
You can change the underlying structure without completely messing up everything that uses your class and even if you change it, you can change your getters and setters so that they transform data the way it was before the change so code using it still works as before, allowing you to slowly change the old code accessing your class without rewriting all of it.
Let's say a while later some part of your program needs to be notified everytime a name gets changed, e.g. to send out gift cards for marriages or whatever, so you want to add a trigger to the change of the name. With public properties, changing that would be close to impossible. With getters/setters, it's easy:
class Employee { private String firstName = "John"; private String lastName = "Doe"; public String getFullName() { return this->lastName + ", " + this->firstName; } public String setFirstName(...) { ... } public String setLastName(...) { this->lastName = newLastName; this->sendGiftCard(); } public String getFirstName() { ... } public String getLastName() { ... }
// Deprecated public String setFullName(String newName) { String[] names = newName.split(', '); this->setLastName(names[0]); this->setFirstName(names[1]); } }
Yes, there are some cases where changing the underlying structure still requires you to change everything, but in general using getters and setters gives you more freedom to change your classes without breaking all the code using it. Public properties are no doubt faster due to the lack of the extra function call but in 99.9% of all usecases, they won't be what is slowing down your program and the benefit of better maintainability is definitely worth it.
Last but not least, getters and setters allow you partial accessibility of properties, e.g. you can use a public getter but a private setter, allowing outside users of your class to only read data, not set it, e.g. the number of elements in an array and similar cases. Before writing both a getter and a setter for every property, think about wether outside users really, really, really need to set it and wether they really, really need to read it.
|
Personally I find it easier to seperate the data from the functionality in seperate classes. So I'd have an EmployeeData (that only contains public properties and no functionality) and an Employee class (that has all required functionality for an employee). Ofcourse also helper methods to convert from/to the associated dataclass, like 'ToDataObject' and 'FromDataObject'.
// Data class, put in a seperate assembly used throughout the application (client, server, etc) [DataContract] public sealed class EmployeeData { [DataMember] public string FullName{ get;set; } }
...
internal sealed class Employee : IDataClass<EmployeeData>, IEmployee { private string fullName = null;
public void FromDataObject(EmployeeData data) { this.fullName = data.FullName; }
public EmployeeData ToDataObject() { return new EmployeeData(){ FullName = this.fullName }; }
... }
The change FullName -> FirstName + LastName is actually a breaking change and breaking changes should be, in my opinion, be carefully considered and it's impact determined.
The change to send a giftcard can be implemented in the 'functional' class Employee without altering the data class. Proper seperation even allows you to make this change without recompiling and distributing the client (in a client/server scenerario).
|
On September 17 2013 02:21 supereddie wrote:Personally I find it easier to seperate the data from the functionality in seperate classes. So I'd have an EmployeeData (that only contains public properties and no functionality) and an Employee class (that has all required functionality for an employee). Ofcourse also helper methods to convert from/to the associated dataclass, like 'ToDataObject' and 'FromDataObject'. // Data class, put in a seperate assembly used throughout the application (client, server, etc) [DataContract] public sealed class EmployeeData { [DataMember] public string FullName{ get;set; } }
...
internal sealed class Employee : IDataClass<EmployeeData>, IEmployee { private string fullName = null;
public void FromDataObject(EmployeeData data) { this.fullName = data.FullName; }
public EmployeeData ToDataObject() { return new EmployeeData(){ FullName = this.fullName }; }
... }
The change FullName -> FirstName + LastName is actually a breaking change and breaking changes should be, in my opinion, be carefully considered and it's impact determined. The change to send a giftcard can be implemented in the 'functional' class Employee without altering the data class. Proper seperation even allows you to make this change without recompiling and distributing the client (in a client/server scenerario). What are the benefits of doing like this? Because it seems like quite an inefficient way to handle data, and I can't see any benefits to this compared to just using normal getters and setters.
|
On September 17 2013 02:30 Tobberoth wrote: What are the benefits of doing like this? Because it seems like quite an inefficient way to handle data, and I can't see any benefits to this compared to just using normal getters and setters. With getters and setter you expose the internal workings of a class. This becomes a problem when a getter returns another class. You can modify properties of the returned class without the container class knowing of it.
public class A { public B b{ get;set; } }
public class B { public int x{ get;set; } }
A a = new A(); a.b.x = 3; // A doesn't know about the change of property x
This makes it very difficult to maintain, write unit tests and refactor the inner workings of class A. Also this can cause huge dependency chains like a.b.c.d.e.f.DoSomething() and thus means that everywhere where one of the classes is used, it is possible to call f.DoSomething(), meaning it can get called when you don't expect it to. It also means that if you have exposed setters as well, anywhere in the application you can do 'a.b = new B()' and suddenly class A does something different. This can also result in memory leaks because objects are not properly cleaned up.
Also, in a multi-tier application with client and server components, you don't want your server components available on the client. In my experience, most client applications are simple CRUD applications (Create, Read, Update, Delete) with the server components doing the difficult work. Therefore all the client needs are the data classes; the only functionality in the client application should be handling the user interaction and related things (client-side validation, user interface, ...) and let the server do the hard work.
|
On September 17 2013 03:08 supereddie wrote:Show nested quote +On September 17 2013 02:30 Tobberoth wrote: What are the benefits of doing like this? Because it seems like quite an inefficient way to handle data, and I can't see any benefits to this compared to just using normal getters and setters. With getters and setter you expose the internal workings of a class. This becomes a problem when a getter returns another class. You can modify properties of the returned class without the container class knowing of it. public class A { public B b{ get;set; } }
public class B { public int x{ get;set; } }
A a = new A(); a.b.x = 3; // A doesn't know about the change of property x
This makes it very difficult to maintain, write unit tests and refactor the inner workings of class A. Also this can cause huge dependency chains like a.b.c.d.e.f.DoSomething() and thus means that everywhere where one of the classes is used, it is possible to call f.DoSomething(), meaning it can get called when you don't expect it to. It also means that if you have exposed setters as well, anywhere in the application you can do 'a.b = new B()' and suddenly class A does something different. This can also result in memory leaks because objects are not properly cleaned up. Also, in a multi-tier application with client and server components, you don't want your server components available on the client. In my experience, most client applications are simple CRUD applications (Create, Read, Update, Delete) with the server components doing the difficult work. Therefore all the client needs are the data classes; the only functionality in the client application should be handling the user interaction and related things (client-side validation, user interface, ...) and let the server do the hard work. Doesn't it make perfect sense that a container class doesn't know about changes to a class it returns by a getter? I mean, take an array class. If something asks for an element, the array class gives away the element, it doesn't care what is done with it. If the container depends on the object, it'd say it's a terrible idea to let other parts of the program interact with it regardless, that's a direct dependence, whether you use a getter, a direct variable call... or throw it to a dataclass first.
|
Getters and setters only expose implementation details if you use them to expose implementation details.
If you grant access to a class with a getter then you better have defined your interface in such a way that it is perfectly acceptable for people to actually use/modify that class. If it isn't, well, don't provide a getter.
|
If your language requires you to write getters/setters then it is probably a terrible language, e.g Java/.NET.
If you don't have a choice however (working in a corporate environment), the debate is asking the wrong question. You shouldn't be lumping Getter and Setter in the same question.
Getters are perfectly fine in any situation and very useful for immutable attributes, in fact there's no point in not having them unless you are just feeling lazy. If it is mutable then don't provide a Getter obviously.
Setters on the other hand are a problem, there are almost no instances where you would need a Setter for an object. If you have setters for your objects you are in the wrong frame of mind and need to do a lot more research on the paradigm of OOP.
|
Hyrule19077 Posts
I feel like we've had this discussion before.
yeah we have back 200 pages ago :D
It all started here.
|
On September 17 2013 10:01 tofucake wrote:I feel like we've had this discussion before. yeah we have back 200 pages ago :D It all started here. Discussion! Gettor/Settor are also good for custom reflection, where you can expose the package of a gettor/settor as a callable property. This is very useful for dynamically enumerating properties of types in order to modify values of instances from a visual editor.
|
On September 17 2013 09:12 sluggaslamoo wrote: If your language requires you to write getters/setters then it is probably a terrible language, e.g Java/.NET.
If you don't have a choice however (working in a corporate environment), the debate is asking the wrong question. You shouldn't be lumping Getter and Setter in the same question.
Getters are perfectly fine in any situation and very useful for immutable attributes, in fact there's no point in not having them unless you are just feeling lazy. If it is mutable then don't provide a Getter obviously.
Setters on the other hand are a problem, there are almost no instances where you would need a Setter for an object. If you have setters for your objects you are in the wrong frame of mind and need to do a lot more research on the paradigm of OOP. Neither Java nor .NET force getters and setters. You can have public instance variables in both of them.
|
Anyone know of a way to put something into a input stream. So there is a default value there.
So instead of
cout >> "Input a number :"; int x; cin << x;
printing Input a number :
it would print Input a number :150_<cursor right here>
For example.
|
On September 17 2013 12:57 Millitron wrote:Show nested quote +On September 17 2013 09:12 sluggaslamoo wrote: If your language requires you to write getters/setters then it is probably a terrible language, e.g Java/.NET.
If you don't have a choice however (working in a corporate environment), the debate is asking the wrong question. You shouldn't be lumping Getter and Setter in the same question.
Getters are perfectly fine in any situation and very useful for immutable attributes, in fact there's no point in not having them unless you are just feeling lazy. If it is mutable then don't provide a Getter obviously.
Setters on the other hand are a problem, there are almost no instances where you would need a Setter for an object. If you have setters for your objects you are in the wrong frame of mind and need to do a lot more research on the paradigm of OOP. Neither Java nor .NET force getters and setters. You can have public instance variables in both of them.
I never said force, I said require.
|
|
|
|