I am going to have another bash at this - I am still in a small way sceptical about some aspects of this. There has been discussion about this before, so I am putting all my thoughts down to see what everyone thinks.
Continuing on from this messages & others in that topic, I would say this:
I think there is a difference between getting a raw attribute versus doing a transaction. For example - "What is your height?" versus "Here are your shiny shoes, please pay me $5". It is easy to see how getters & setters used in the context of a transaction could be very bad. From rude / threatening "How much money do you have?" to theft - "Take $1000". So I fully agree with the idea of using a design pattern for transactions as per the article
ne555 quoted.
It is important to provide an interface for objects - without it they are pretty much useless. For a circle one should be able to enquire about it's centre point, Radius, Area & Perimeter. A get function for a raw attribute might be a necessary part of that interface, even when used in conjunction with a design pattern.
Also there is a distinction between a setter that is straight assignment (Bad) versus an Update type function which might do permission & validation checks & recalculate other member variables in the process. An Update function could also be part of the interface.
Then there is the level of knowledge of the programmer. Things like design patterns could be way too much for a beginner & far past the requirements for their assignment. Although one should strive to have elegant solutions, a lesser one might OK for small programs like a typical high school assignment.
So what about these points, presented in order from very bad to good:
1: Public variable
Good points: None.
Bad Points: Anyone can change it & invalidate the other member variables.
2: Protected variable
Good Points: Dead easy - it's not public any more & derived classes functions can access it directly.
Bad Points: It works really well, until the type needs to change or is extended:
Article wrote:
Today an "identity" is a name; tomorrow it's a name and ID number; the day after that it's a name, ID number, and picture.
|
Any code that uses it must be changed to reflect the new situation. Can't alter any computation because it's just a variable.
3: Private Variable with Public functions
Good Points: Can change some computation inside the function without the client being any the wiser. Any object outside the class can obtain the value of a raw attribute. Can provide functions that update several variables at a time, and those that display variable values. A selection of the functions form the interface for the class.
Bad Points: Still can't "Future Proof" against change in type or extension as above.
getters & setters for each member variable is just the same as making all the variables public. So the designer needs to decide what info should be available.
4: Promote The variable to a class
Good Points: Now we have a better chance to "Future Proof" the info. We can do all kinds of things in the class.
Bad Points: It is more complex.
5: Use Design Pattern/s
Good Points: There is now all kinds of flexibility, reuse, decoupling etc.
Bad Points: Even more complex, but worth it. There are some adverse consequences which need to be considered.
So it seems that trivial getters (returns something), and setters (straight assignment) are the real bad boys here. Compare to those functions that conditionally have the same result, but do checking & validation. Some functions might not need much checking - think getRadius.
It also seems that the classes Design Patterns deal with still have get functions in their interfaces, but they are coupled only to the DP class, and not to all the other classes.
There you go - that's my thoughts for today. I look forward to any replies, which I read tmrw because it's 03:00AM here - again!!