31
Oct 06

Yet another accessors/mutators discussion

In the last few months I followed and participated in numerous discussions about getters and setters.  From the topic popping up in various discussions on framework design, OOD, domain models, and the popular (if not in the number of readers, at least in the number of critics:-) article from Allen Holub about why getters and setters are evil.

Of course the programmers that have designed numerous applications/frameworks that participate in what to me is procedural programming with OO idioms, will be very defensive (it’s human nature).  I used to use accessors blindly as well, since it was easy and made sense.  Hey, we’re still encapsulating right?  Access to the field is now behind a method call, so the implementation is not as tied to a particular state field.  That’s a load of crap and I wish folks would truly stop defending such horrific practices.

In no way am I saying that access to all internal state is bad, but access should reflect a meaningful business method, not simply retrieving an internal implementation detail.  Yes, in some trivial apps in might not make sense and in others it might increase the amount of code drastically, but that’s relative to someone having to read the loads procedural crap in the future with all the object messages being passed around all over the place.  Good OO design principles are all about encapsulating the state, though limiting the amount of messages flowing through the system.

I mean, if I have something to say and I can speak, I’d rather say it myself thank you, rather than have someone query me about what’s on my mind and say it for me.  It’s just basic design principles.

Now, today, yet another thread on TSS brings up the topic of reducing the amount of typing people have to do while generating getters/setters.  How about reducing the amount of getters/setters?  Have anyone though of that before?  It’s like EJBs (pre-3.0) all over again.  Let’s create code generators to generate a bunch of stubs vs. actually fixing what’s wrong with the design to begin with.

Well, nothing unusual about the thread, other than David Bernard pointing us to a link that states…

"I keep my code cleaner and clearer. : Use public attribute as property, instead of private attribute and accessor methods."

What?  This can’t be true.  So we now take the horrific practice of exposing state, but at least through accessor methods, which makes us less implementation dependent [as the method implementation can be changed without effecting the signature and return type] and replacing it with public access to internal attributes?  Wow, I’d really love to see a non-trivial app build that way.  Actually, no, I would love to fly to the future and meat the person that has to maintain and extend the app in the future.  Poor soul.

Ilya Sterin

19 comments

  1. The problem with getters and setters is that it is a convention. If you take it high level enough (OOA – OO analysis), it is bad practice to define a method where there should be an attribute and vice-versa. Why? Because attributes a elementary data, which talk about object properties, while methods talk about operations that can be applied to the objects, or data that can be derived from other elementary data. As an example: class Person { int yearOfBirth; String name; int age; } is not good analysis because yearOfBirth depends on age and vice-versa. So, from an analysis perspective you can make a choice of saying that the year of birth is more elementary that the age (which makes sense) and define the age as a method. class Person { int yearOfBirth; String name; int age(); } This is clear an makes sense from an OOA perspective. It is OK to show the state because it is part of the functional definition of the object. Now, from an OOD (design), when you are dealing with a language like Java that supports and encourage the use of interfaces, it is good practice to use getters/setters. Then a framework layer like a J2EE app server can intercept access to the field using simple techniques such as proxying (dynamic proxies being the most practical probably). So, you are safe, while it is much harder to intercept field access. That’s the only reason why people do not use public attributes in Java. Now, the drawback of this getter/setter technique is that it opens the door to variations on the public attribute accesses, so that you never know anymore what is an elementary attribute and what is not (the getter could implement any transformation on the state). From an OOA perspective, all this is not very good, but it is ok, because then you end up having only a private state and no public state. Basically, you would have: class Person { int yearOfBirth(); String name(); int age(); } And you do not really know what is calulated or not. The only way to know that, it to add the naming convention and pray that programmers will follow them. class Person { int getYearOfBirth(); String getName(); int age(); } But nothing in Java will enforce this naming convention. Note that with Spoon, you can analyse the code of your getters/setters to check that they behave correctly. That might be another way to go (rather than generating the getters/setters automatically. Something like: class Person { @Getter int getYearOfBirth(); @Getter String getName(); int age(); } … would totally work with Spoon and could prevent the programmers to overload the getters/setters in a wrong way. // BTW, how do you format code here?

  2. “So we now take the horrific practice of exposing state, but at least through accessor methods, which makes us less implementation dependent [as the method implementation can be changed without effecting the signature and return type]” 80% of getter and setter are the stupid code (lot of time generated by IDE). If you change the implementation : * if the change is local to your project, you could simply refactor your code and use a method. * if the change could affect external project, in every case, it’s a new version, so external project need to upgrade their dependency (that done in design time in java world vs C world). So the change could also be done by changing the API into the new version. But If you want to keep the field access syntax, AOP can be used to intercept field access (eg: add observable behavior, add contract (pre/post/invariant), add field relation , add access restriction). I don’t need to drive a truck for shopping if a car is enough. I’ll drive a truck when I’ll buy sofa. I think that simple/readable code is more upgradeable and easiest to maintain than code with academic heavy pattern. I saw more drawback to always use getter/setter than public field. IMHO academic practice must progess with tool. Getter/Setter practice is pre-AOP, pre-refactoring, pre… and date from the “encapsulate every thing” time. public field for data and method for behavior. K.I.S.S

  3. Extract from the GetSet’s FAQ : What are the advantages of public attributes (vs getXxx/setXxx) * It’s the natural way to declare and use it (before the Getter/Setter practice). Other modern programming language (C#, D, …) or scripting languages (Groovy, Beanshell) manage public attribute like property. * More readable declaration (no need of methods or annotations) * Less typing (declaration, call, javadoc) when you create a field (and no need to call IDE Generator), and you refactor it (with tool or by hand) : rename, remove, update comments… * Easy to keep attribute, getter, setter in synch (name, type, comments) : localized in one place * More concise/compact/readable code and javadoc (in source and html generated) * No more work than with getter/setter when the internal structure changes : 90% of the time get/set reflect the internal structure, and the caller must follow changes. * More readable for caller code (IMHO) (less (), visibles changes of attributes…) * Already compliant with IDE and compiler (javac) And why not using public attribute ? it is in java since the beginning.

  4. Renaud, I don’t disagree that Spoon is a great tool in today’s environments, but I think you’re missing my point. I’m not saying that today’s accessors/mutators should have better language support vs. done by convention, rather I’m advocating the fact that they should rarely be used period. There is no reason for a domain class to allow access to it’s internal state. Your Person object is a prime example of a value object or what we also might call an anemic domain object. It is used throughout the application and has no or very minimal behavior. In most cases, the data that you are requesting from this domain object, is to perform some sort of an operation, which should be performed by the object itself (the one that encapsulates that state). Today’s frameworks are very poorly designed in a way that they are all dependent on some sort of an accessor strategy. Mutators are not as bad when used for dependency injection purposes, but I’d strongly advocate constructor based injection, which will work in most cases and though allow you to either make your objects immutable and/or limit the amount of it’s variance. A very simple example of this is say you need to print out the person to a PrintWriter interface… class Person { private int yearOfBirth; private String name; private int age; public void printMe(PrintWriter out) { out.print….. } } Again, very simple. In more complex cases, there are various patterns, like builder that you can employ for more complex exporting capabilities. See my posts on TSS about that and of course the arguments provided by others, which I still think are pretty poor.

  5. David… “80% of getter and setter are the stupid code (lot of time generated by IDE). If you change the implementation :” Again, that’s not the issue, the issue is that software designed to expose its implementation state is not designed very well. Objects should be as self contained as possible and rarely have to expose state. “I think that simple/readable code is more upgradeable and easiest to maintain than code with academic heavy pattern.” Not necessarily true, depending on what you mean on simple readable code. For a trivial application, you can stick everything in the main method, it will be very readable and procedural, probably more so than if you encapsulate your concerns within their own domain objects, but once your application grows, it’s suicide, I don’t think I need to go into elementary details of why. Also, not sure what you mean by academic heavy patterns. Design patterns are not academic, they are extracted from common solutions developed by real developers that faced these concerns over and over again. “Extract from the GetSet’s FAQ :…” Again your missing the point. It’s not about helping developers cope with get/set by allowing a less code intensive way to bad design. I’m trying to make the point of not using getters/setters period in majority of the cases. Ilya

  6. About avoid usage of getter/setter. I was for it. If we take the printMe(), toXml()… examples. I’m against: You show internal state into predefined format : * those format aren’t usable without some processing to extract information. * what append if I want another format ? * what append if I want to use GUI ? I prefer to delegate to a service the goal to format data… separation of concerns. Using visitor or iterator isn’t a lightweight solution, and don’t match every case. OOP is based on analogy with real world : I’m a Person and every body could see I’ve got 2 arms, 2 blue eyes,… I can’t change my heart, but a doctor can. An other example : the String class. The JDK 1.0 provide String with a limited behavior and encapsulate internal state. But creator can’t provide all behavior, so developers create Helpers (like ToString from commons-lang). A real example (from my last project) : I create a Deal class that hold data about deal (read from RDBMS). The deal hold several amount (quantity + currency). To change the unit of amount I called amount.changeCurrency(newCurrency, changeAt). Because changing unit require external data of the Amount class (like the table of rate for each day). I move outside of amount the changeCurrency feature. I create a ChangeOffice (analogy to reality, 1 US$ doesn’t change itself in other currency). Creating Data Object without data accessors and with only behavior seems to be very difficult. Computing is input/transformation/output. IMHO 100% pure OOP application (without properties, struct like,… like I learnt 10 years ago) isn’t realistic. Application programming is a merge between procedural, OOP / Nacked Object, AOP, data/service design, … The mixture depends of context (skill of the team’s members, target environment, …).

  7. “About avoid usage of getter/setter. I was for it. If we take the printMe(), toXml()… examples. I’m against: You show internal state into predefined format : * those format aren’t usable without some processing to extract information. * what append if I want another format ? * what append if I want to use GUI ?” The example I outlined is only relevant to a very simple use case. As I mentioned, there are other various ways of accomplishing it. My preferred way is the Builder patterns. I would also opt for having some value object that gets populated by the domain object and then passed around to some service for information extraction. Value objects are OK to have accessors/mutators, as they don’t really contain any implementation, rather state. Immutable value objects are even better. That’s my biggest problem with say the detached persistent objects with Hibernate, JTA, etc… Though it seems like a nice way to get rid of Transfer Objects that we used to use with pre-3.0 EJB, I think TO/VO is still an elegant way of not exposing domain state. If you look at some apps today, the entity objects that are your business domain objects are anemic. They basically have a bunch of getters/setters for use with persistence frameworks and then get detached for use with an MVC framework. Where in the heck is the business logic? Ah, it’s scattered all over the place and/or embedded in some monolithic service interface, which is basically a procedural model (Transaction Script). Services should encapsulate use cases, not domain specific logic. The service should forward any domain specific calls to the business object. Ilya

  8. Hey guys, I am sorry but I do not believe this discussion will lead us to an absolute answer. First you have to decide at what level you are speaking: analysis or design. Hidding the object state is already a design choice to me. So, I think that both visions are good, they just don’t stand at the same level (that is why you will never agree). One vision privileges the designer/developer making choices and advocates a design good practice (hidding state), while the other one is more an MDA/Generative approach where the primary concern is to leave the business model as free as possible from design decisions that would pollute it. BTW, the getter/setter case is IMO a minor case of this dilemna. After that, you might want to ask yourself if you want to generate a proxy, a factory, or a visitor pattern! I used to be pro “generative approach” because I thought it would be possible to get good tools to implement it. However, it poses a lot of technical issues (especially when you start using it a lot) and it easily becomes a mess when the programmers want to get control on the code. Maybe one day we will have the technology for it, but in the mean time, it is only applicable to small cases (like getters/setters). As a consequence, I turned out to advocate the “validation approach”: no generation, but the IDE should tell the programmer when the program does not follow some good practice rules. For instance, it could report a warning when accessing the internal state of an object. Of course, this could be customizable depending on the programmer… Although it support generative programming, validation is exactly the goal of Spoon (see the VSuite Spoonlet: http://spoon.gforge.inria.fr/SubProjects/Main). Note that generative programming can even be used as a way to define quick fixes. This makes a lot of sense when the programmers want to keep control of what they are doing (good practice is not good for everybody). By the way, after all this, I think that I will add a vsuite processor that checks that the object’s state is not accessed directly. I know at least one potential user 😉

  9. what is “Enteprise”? Is that a typo or are you mispelling it on purpose? Just curious 🙂

  10. Renaud, that’s funny. I can’t believe I mispelled it, didn’t notice it, and actually didn’t notice it until now. I wonder if everyone else noticed and just didn’t say anything:-) Thanks a bunch.

  11. I didn’t post that. And I do not see where your wrote it. It is not an English word, for sure…

  12. “One vision privileges the designer/developer making choices and advocates a design good practice (hidding state), while the other one is more an MDA/Generative approach where the primary concern is to leave the business model as free as possible from design decisions that would pollute it.” Why continue to say that “state must be always hidden” is a good practice ? Today I no more see the need to hide the field of Value/Data/Transfert Object. I don’t say that all state must be exposed, only state/property used by others. And my purpose is if I expose a property with getter and setter why not exposing directly the field ? (see the extract of FAQ I copied/pasted above). Why the designer/developer can’t leave the business model as simple as possible ? (I’m a designer/developer) What against a “procedural” approach (sometimes), if the code is readable, match the analyze, allow extension (event/service driven architecture),…

  13. The answer to that is simple. Hidding state is a good practice because you want to postpone design decisions as much as you can, until you really know the context of use of an object. Example: class Circle { double diameter; double surface() { return 3.14(diameter/2)(diameter/2); } } It makes sense from an analysis perspective to define the state of a circle to be diameter, because it look like it is the elementary data here. However, later, you might find out that this model gives very bad performances because you mainly use surface() and you need it to be fast. In that case, you may want to change the way you model the state of a circle: class Circle { double diameter() { return sqr(surface/3.14)*4; } double surface; } So it all depends on your context of use. And if you have hidden your object state completly, you can tune your objects to behave well for all contexts (just by changing the internal state representation). Note that there are ways to optimize you programs in a kind of automatic way – exactly like you do in GetSet. With AOP or generative programming, you can add code to cache the value of the surface – for example – or you can even change the state representation with an aspect. However, I do feel that the basic solution I have just given is more simple and easier to understand for most programmers. Again, it is just a matter of choosing between both visions I was talking about. GP or not GP? That is the question.

  14. David… “Why continue to say that “state must be always hidden” is a good practice ?” Because it’s the basic priniciple of OO design “encapsulation”. You do not want to expose the state as it then becomes the interface and cannot be modified, though your implementation is not constrained by providing a certain interface. I think you are talking in terms of trivial apps that are self contained and developed within the same IDE. You can refactor, redo things on demand. That’s usually not the case in enterprise apps that reuse various libraries, have multiple components, layers, etc… Even in a dumb object like VO/TO, etc… that do not contain any domain related business logic, it’s a good idea to abstract the access behind an interface and/or behind getters/setters. That’s the only time I advocate using accessors/mutators, as they provide a nice abstraction and hide the implementation that can later be changed without breaking the public interface.

  15. I agreed with you sometime ago, not now. * Renaud : “you want to postpone design decisions as much as you can…” Why? Planning evolution and extension point mismatch the needs when they appear in 80%. So you add complex code “in case of ???”. I work on lot of application or library with encapsulation, extension point… But when I have to add new feature, I need to change/understand/maintains more code than what is really needed. You can refactor, redo things on demand. That’s usually not the case in enterprise apps that reuse various libraries, have multiple components, layers, etc… Your 2 circles implementation advocates my opinion, you can’t hide your 2 Circles implementation with the same interface : setter are different. Show me a OOP model that support the 2 implementations. * Ilya : “I think you are talking in terms of trivial apps that are self contained and developed within the same IDE. … That’s usually not the case in enterprise apps that reuse various libraries, have multiple components, layers, etc…” No, I talk about application, libraries, framework… In the enterprise (like other context) : you don’t change/upgrade dependencies/libraries directly in production. You validate new version of those dependencies before, check of the API and behavior… And If you are in the design/coding cycle, then you can refactor the code to follow the dependencies’ changes. I agree with encapsulation, interface for service and behavior, but not for getter and setter (VO/TO). * Keep It Simple Stupid * XP : “What is the simplest thing that could possibly work?”

  16. Your 2 circles implementation advocates my opinion, you can’t hide your 2 Circles implementation with the same interface : setter are different. Show me a OOP model that support the 2 implementations. < Well, typically we use a factory pattern: interface Circle { double getDiameter(); void setDiameter(double d); double getSurface(); void setSurface(double d); } class Circle1 implements Circle { double diameter; double getDiameter() { return diameter; } void setDiameter(double d) { diameter=d; } double getSurface() { return 3.14… } void setSurface(double d) { diameter=sqr(d)… } } class Circle2 implements Circle { double surface; double getDiameter() { return sqr(surface)… } void setDiameter(double d) { surface=3.14d… } double getSurface() { return surface; } void setSurface(double d) { surface=d; } } interface CircleFactory { Circle createCircle(); } And then you can get a different implementation of circle factory depending on your context of use. That said, I am not saying it is simple (it is not KISS ;)). It requires some refactoring of your program, but it works and it is extensible (you can add new types of circles for new contexts). Also, I agree that if you do not need to have several implementations of your classes, why would you ever bother with this?? I am with you in the sense that you should use the simpliest solution that works (XP), and that you should refactor to tune it, only when the need arises. This statement of XP is kind of dangerous though. Sometimes, you go for the simplest solution and you find out a new requirement or concern that makes your choices so invalid, that it is impossible to refactor your application (even with a good refactoring tool). Once again the get/set issue is kind of simple and refactoring should be ok. It is not as simple for other idioms or patterns.

  17. David, refactoring is in most cases a byproduct of poor design, therefore refactoring tools exist to change/manage the original design decisions. With the right design decisions, refactoring should be minimal and code maintenance and extensions should be allowed with the design conventions rather that with refactoring tools. I don’t think we’re saying that your approach is not say faster and simpler for certain things, but that doesn’t always equate to maintainable/extensible application that can withstand various changes in the future. Ilya

  18. Free Proxy Server Software

    Proxy Scanner Server Etlin HTTP Proxy 1.0.0 HTTP Proxy Server , 142 Proxy Finder

  19. External Proxy Servers

    block internal to access For authenticating HTTP proxy The i

Leave a comment