DEV Community

Avoid getters and setters whenever possible

scottshipp on December 08, 2017

Noooo!!! Don't click that generate getters and setters option!!! I like the rule: "Don't use accessors and mutators." Like any good rule, this on...
Collapse
 
galdin profile image
Galdin Raphael • Edited

I love C# 😬
Edit: C# Property Design Guidelines

Collapse
 
dilantha111 profile image
Dilantha

Actually when I just started reading this article. C# is what came to my mind instantly.

Collapse
 
jodydott profile image
Jody Dott

I think C# is even worse in this regard.

The argument is that getters/setters and properties VIOLATE ENCAPSULATION by exposing internals as properties rather than mutating through behavior as classic OO would prescribe.

I've seen excessive use of getters/setters/properties in Java, C#, Ruby, and Javascript. Changing the syntax does not help. If anything it aggravates the problem by telling people that its ok to set attributes willy nilly and separate the logic that dictates the behavior from the object.

Thread Thread
 
aminmansuri profile image
hidden_dude

I've seen huge problems in Ruby where people create "models" and then set all the attributes but forget to encapsulate the "rules" and behaviors around those changes. So later it becomes a huge mess to figure out how the class actually works.

If your "objects" are just a bunch of attributes with just getters and setters then they aren't really objects. They're structs (as in C structs) or records (as in Pascal). And you aren't really doing OO. You're using an OO language to do procedural programming.

Collapse
 
florianschaetz profile image
(((Florian Schätz)))

Oh sweet mother of mercy, no. I am currently forced to work with code where someone once decided that getters and setters were evil and did everything with public variables. It's... not good. Yes, 95% of the variables work that way (because we have lot of them), but the remaining 5% make more work than it's worth.

Also your example "gasAmount" is completely nonsenical, because the problem exists no matter if you use getters/setters or just a public variable. How does a public variable with the same name change that problem?

Also your debt example is a perfect example why getters are BETTER than exposing the variables. With a getter you can protect your list by returning a copy. With direct member access? Not really.

So, your arguments against getters and setters are not really good. That's unfortunately, because the basic idea is not a bad one:

While getters/setters ARE better than directly exposing the member, we should of course try to prevent BOTH.
Immutable objects, for example, have far less problems than mutable ones - and if all members are final and imutable themselves, they can be exposed as public members directly, because it's read-only. But the problem this solves is not that getters and setters are but, but that mutability is more dangerous than the other way.

Collapse
 
bobbypriambodo profile image
Bobby Priambodo • Edited

I think you're missing a bit of the point there.

Scott wasn't comparing which of the two (getters vs. public variable) is better. What he said is that getters and setters by default (e.g. when automatically generated by IDE, or shown in beginner examples) expose the variable just the same as making it public; however, people seem to appreciate getters more than public vars, even when they're essentially the same.

The point is reinforced in your last sentence that, above all, the problem is mutability.

Returning copies are not getters (or at least not what most think as getters); they're essentially behaviors. You have to do the extra work to make them only as exposed/encapsulated as necessary.

The point I took from this article is to always strive to make your variables private, and that means not even getters and setters, and only expose behaviors around that data. Which I think makes sense, with some caveats that also have been stated in this article. Not necessarily agreeing, but a good food for thought nonetheless.

Collapse
 
florianschaetz profile image
(((Florian Schätz)))

That's what I said... "the basic idea is not a bad one" - it was just surrounded by bad arguments for the wrong problems. By starting with the public member thing, the whole text got the wrong spin from the start and the following bad argument didn't help.

Directly addressing mutability, exposing behavior, adding methods that directly work on the members instead of just holding them in a dumb object, etc. is a great idea. But by surrounding it with discussions about public members vs. getters/setters, etc. just dilutes those great points.

Thread Thread
 
bobbypriambodo profile image
Bobby Priambodo

I see, and that I can agree with. Hopefully the readers can see beyond it too. Thank you for elaborating!

Collapse
 
hrmny profile image
Leah

In the debt example he didn't argue for public variables though, I think you misread that?

He said it wasn't good to expose it at all, but if you do with a getter that returns a copy.

But the better alternative is doing what you want to do with it in the class itself

Collapse
 
akostadinov profile image
Aleksandar Kostadinov

Yeah, it's too bad many inexperienced developers will not understand that this is just clickbait. Thank you for the great comment. I couldn't do it better.

btw the example of famous person being against setters/getters seem to be about very specific use case.

Collapse
 
xowap profile image
Rémy 🤖

Well, I used to think that getters and setters are usually useless. Until one day I had to do some computations once a value was set and there I had to re-factor my whole code around the fact that the member was no longer directly accessible but had a getter and a setter.

So I'd say, putting getters and setters is more future proof whilst not being very expensive.

Yet I'd also say that this problem almost only exists in Java because other languages have ways around this (Python <3)

Collapse
 
jodydott profile image
Jody Dott

the computations should happen inside your object (in a OO world) you shouldn't be asking other objects for their internals (unless they are simple value objects).

Collapse
 
xowap profile image
Rémy 🤖

Yup but sometimes you start without needing the computation and then later realize that you need it for a new feature. In that case, it's hard to come back on your decision.

Thread Thread
 
jodydott profile image
Jody Dott

That's why you should program with an OO style and encapsulate. All requires computation.

Collapse
 
rafiq74 profile image
rafiq74

I was about to mention the same thing. I had the same experience many times.

Collapse
 
dimpiax profile image
Dmytro Pylypenko

You have just shown bad design. Reason not in getter/setter, but in approach.
If you open properties to public you must have reason why. But not like exception with debt example.

If replace getter/setter theme with singleton or composite – and write in the same manner, the result that all is bad, will be the same.

Main point: use features properly. We have instruments in our belts, and to hammer nails with a saw is not the best choice.

Collapse
 
scottshipp profile image
scottshipp

Hi Pilipenko, my goal with this article was to show bad design. All of the code examples here are things I would not do, including the debt example. I tried to give guidelines for what I would do in the section at the end, but I probably could follow up with code examples of what I think people should do.

Collapse
 
dimpiax profile image
Dmytro Pylypenko

But your topic name is "Avoid getters and setters whenever possible", not "Bad design in getter/setter". This article just discredits specific area of programming, but not educational.

We have a lot of useless articles like "Don't use OOP", "Don't use functional programming", "Why declarative worse that imperative" and so on. But whole idea in right usage, and neither getter/setter neither functional or AOP are not bad.

Thread Thread
 
xtofl profile image
xtofl

I must say you have a point: we lack a vast body of "how to do X without violating design flaw Q".

This year I learned about Domain Driven Design, and the Onion Architecture, where they design apis around use cases instead of data. Maybe there is some source of positive guidelines we can tap.

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

Very good write up. I had an undefinable suspicion about getters and setters, but you've helped cement it for me. Thanks for the much-needed kick in the teeth for us OOP purists! :)

I'd like to add to this, if you are only using a class/object for storing data, you've got bigger design issues than just getters and setters. Read Pseudo-Classes and Quasi-Classes
Confuse Object-Oriented Programming
by Conrad Weisert.

Collapse
 
aminmansuri profile image
hidden_dude

Getters/setters are not OO constructs.. they are inherited from "construction by parts" popularized by languages such as VB and PowerBuilder.

You'll find no such horrors in the old smalltalk codebase (though VisualAge for Smalltalk did have properties because it was a construction by parts system).

So if you were an OO "purist" you would have long eschewed getters and setters.

Collapse
 
codemouse92 profile image
Jason C. McDonald

Fair point. OOP, as Alan Kay (Smalltalk) envisioned it, is nothing like what we have today.

Thread Thread
 
aminmansuri profile image
hidden_dude

Thanks for the paper by the way.. very interesting.

Collapse
 
scottshipp profile image
scottshipp

Thanks for this paper Jason! It is great!

Collapse
 
kallaste profile image
Tatiana McGarry • Edited

Getters and setters are an integral part of encapsulation in OOP. Yes, things can go wrong when you abuse a setter, but unfortunately, there is no such thing as "idiot proof" code. It used to be that programmers themselves were expected to have brains.

Everywhere I look there are new "suggested practices" popping up that seem to want to guard against someone else's poor programming messing up your code in the future, when unfortunately, that simply cannot be done. The suggestion to "avoid getters and setters whenever possible" is just another example. But inexperienced developers read an article like this one and just jump on the bandwagon. How about we simply omit them when it makes sense to do so?

Just program responsibly and think about your use cases when you need something to be inaccessible and/or immutable, and stop handicapping yourself trying to guard against any remote possibility of some future developer using poor practices in the future.

Collapse
 
aminmansuri profile image
hidden_dude

They are not part of encapsulation. They are the opposite.

An encapsulated class in "pure OO" does not expose its properties. But many people confuse this because their only exposure to "OO" has been through Java and C# (and their successors) and have had little exposure to a real OO system like Smalltalk.

Collapse
 
kallaste profile image
Tatiana McGarry • Edited

Yes, they are a totally legitimate part of encapsulation in the current paradigm of Object Oriented Programming, and will be mentioned as such in current literature about it. That isn't confusion, it is the maturation of programming language concepts. A lot has changed since 40 years ago when Smalltalk was invented. We had no idea what OOP was going to be back then, or in many ways how it was going to be used.

The argument that getters and setters aren't a valid part of encapsulation because Smalltalk did it differently is a little like debating what the World Wide Web is on the basis of how things were done in ARPANET. Quite simply, just not very relevant.

Thread Thread
 
aminmansuri profile image
hidden_dude • Edited

No. Its a misunderstanding about what encapsulation is.

If you have a computation like:

bankAcct.setBalance(bankAcct.getBalance() * bankAcct.getInterestRate())

Then you aren't understanding how OO is supposed to work. The correct encapsulation would be by having behavior based method:

bankAcct.accrueInterest()

Getters and Setters don't come from OO they come from "construction by parts" a style of programming made for automated UIs like in VB. It has its place, its related to OO, but it isn't encapsulation. It's the opposite. Its exposing your attributes to the outside world.

And plenty of OO was written by great programmers like Kent Beck and others that later helped influence how we did it in other languages. But the popularization of many techniques has little to do with good OO, and simply popularization of stuff that certain developers promoted.

Collapse
 
tmfrisinger profile image
Travis Frisinger • Edited

Fantastic stuff! Ultimately, it is the lack of encapsulation and presence of mutability that are the real problems. It is not a style or language issue, rather, it is the lack of awareness from developers to push for better solutions that do not rely on 'cheap and nasty' to do the job.

Collapse
 
wrongabouteverything profile image
wrong-about-everything

Totally agree! Accessors is totally anti-OOP feature. I believe it was Martin Fowler who popularized a reprobation of this concept in his post Anemic Domain Model. But little changed from 2003. A lot of people still are not aware that the whole point of OOP is combining data and behavior. Thus accessors still don't make any sense there.

Generally, the $64k question is how to come up with such an objects that expose only behavior, not data. Well, my take on it that it all starts with the problem space -- your concrete domain at hand. Talk to your business-experts, consider the use of CRC-cards, draw use-case diagrams and find your smart and knowledgeable objects.

Collapse
 
aminmansuri profile image
hidden_dude • Edited

There are some solutions to the getter/setter problem but they aren't great. Like using a visitor pattern to feed data into a view, or using "renderer objects". Part of the reason for getters and setters is the more pressing desire to separate model's and views.

But I agree that from a purist point of view, getters/setters are not really OO and they violate encapsulation.

Collapse
 
arhanger profile image
Arhanger

Someone has never changed his code. Sorry, but afet this "In both classes, Car1.java and Car2.java, we get essentially the same result" i stopped reading. Public properties are not the same as getters and setters. With getters and setters we have an entry point to our business logic, with public properties we don't have any. After changing hundreds of calls to any property through the whole project you'll understand why. This is the first point.
The second point was mentioned in comments. Calls by reference. When you use public properties you usually don't bother with copying stuff. Why should I? Doing that hundred times. That leads to a couple of painfull bugs. The most common one are date objects being modified by reference. Hours thrown away trying to debug that one. Especially by middle/juniors.
Third, getters and setters can be covered with unit tests. If someone changes something you will see that.
The last and not least. It's a lot harder to control workflow with this approach. Instead of reviewing code design, you are forced to check every property call through the whole project. Not very effective.
It's not bad to try to find something new, but getters and setters are used not by chance. If you want to remove a tool, propose something to cover that gap. Good luck.

Collapse
 
mduran profile image
Miguel Duran

It shows that you stopped reading at that point. His point was not that public attributes are just as good or better than getters and setters, his point was that the internals of a class should be as restricted as possible and having getters and setters violates that.

If you actually read the article, you would see this:


```My "default" is to start with a private final member, set only by the constructor. No getter or setter!

If another class absolutely needs to see this member, I think about why. I try to see if there is a behavior that I can expose instead, and create a method for that behavior.```

Collapse
 
arhanger profile image
Arhanger

My points wasn't on good/bad. He said that both ways give you the same result. And this is wrong. That was what I wrote about.

Second, but not least. Getters and setters can also be restricted, if you need that.

Third, there could be dozens of parameteres. Constructor will become huge and I personally don't like that. For that I'd better use a factory, that will garantee to create a valid object. For any other call there's code review to deny them.

Fourth, there's metaprograming in many languages. That lets you use even private members. So I don't see a reason to be so paranoic about that. But private members could give you headache when writing unit tests or changing class with tens of references to that private member.

To conclude, my main point was that these two methods don't give you the same result. Hope that makes my thougts clearer.

Collapse
 
pocketstealer profile image
Pocketstealer

Get/Setter.

Why? Because it's easier to say in a set:
If(Value not null){
set value
}
else{
w/e
}

Than to go EVERYWHERE and check if that value is null then use something.

Sure a basic example looks stupid... but you were not taught not touching the flames by being explained what thermodynamics are...

Get/Setter's are better for a good approach and have assurance that the class will work no matter what the values will be given.

PHP is a loosely typed language getter/setter are perfect for this.

Collapse
 
scottshipp profile image
scottshipp

You're concerned about code duplication and that's a good concern. But what if there's a bigger issue here? The fact that this setter can be called "EVERYWHERE", as you say, is a bigger problem to me. Everyone has access to set this value. If just one of them makes a mistake, everyone else using it suffers the downstream effects.

So the real problem here isn't duplicated code, to my mind. It's the fact that there's a variable available everywhere. That sounds like a global variable with some procedural code manipulating its state.

Consider what happens if the field is kept private, and no get/set methods are made public either. Where is everywhere now? Only inside the class itself. It's not a global variable anymore. There aren't a bunch of random classes out there that can go set that value. Another developer can't come in with some new code that calls set on that value incorrectly, and stops several user scenarios from working correctly.

I think we've all worked in scary code like this and we can do better. In my experience, I've found that looking at everywhere the set method is called yields the result that I come out with at most a few different uses, and I can write a method for each use and call the new method from these call sites instead. They'd be behavior methods which keep that variable inside a class or at worst inside a package, and not available everywhere. That way I not only de-duplicate code, but I prevent other bugs that could occur as well. Bugs like the site header one that I mentioned. When no one can call setWhatever(newValue)--indeed they don't even know that the Whatever variable exists--then those kinds of things aren't possible.

Collapse
 
jstormes profile image
James Stormes

In PHP we also use reflection for hydrating objects. If all your objects properties have getters and setters you can hydrate by reflection, otherwise you have to write lots of exchange_array code.

However we can also hydrate on properties directly, but you don't get to do any validation of the data. As you say PHP is loosely typed, so that opens you up to hacking/injection.

What is harder to do is hydrate on both get/set and properties. So you wind up all ways using setters, even if you don't need them all the time.

Collapse
 
pocketstealer profile image
Pocketstealer

I think we are confusing bad practice with the role of getter/setter.

Bad practice is everywhere. But when you are using a getter/setter you expect to give a certain value and get a certain value.

You know you are setting a string. You will get a string. Thats the role of the getter/setter.
You are certain and sure that there will be in no circumstation a null there. Or a number. Always a string.

Using getter/setter for everything is bad as well. Leaving a variable there that is used and can be moddified to contain anything is even worse.

If you use get/set just to "return","$this->alfa = value" that's bad practice.

But a beginner doesn't know when should use it or not. So the one that's easiest to "implement after" it's the cheapest.

Scope of projects change. Agile is here and not always you have time to get all the information/specs or maybe some new information get there with constraints.

Always take the safest/easiest way rather than "smart way but it might blow up later".

Collapse
 
elcotu profile image
Daniel Coturel

Hi,
I don't agree with expressing that package private attributes are a better approach than getters and setters.
Suppose you have the case of a bag of properties as you stated in the data use case. A bag of properties may be abstracted as a case of class with state but not behaviour.
Now, let's suppose that, in any time in the future, you have to add behaviour to one of the attributes.
If you implemented the getters and setters, then you put that behaviour in the corresponding methods and you are done.
If you didn't implement those getters and setters, you have several choices to make:
1) Put the new code without being coherent with the rest of the class
2) Refactor all the class to make it coherent and then include the new behaviour
3) Put the behaviour in the calling classes
Maybe I'm missing some point, but I don't see the advantages of the second option.

Collapse
 
scottshipp profile image
scottshipp

I didn't understand your option 1, but I would definitely not do option 3. If I understand right, option 3 would mean you go and duplicate the new behavior at every reference to the member. Option 2, then, is way better than 3 in my mind.

For option 2, since it is package private, I would expect the number of references to that field to be fairly limited. How large is a package usually? I'm sure it varies depending on context, but generally its manageable. I personally wouldn't expect more than a few places inside a package where there's a direct reference to a given field. Maybe I make smaller packages than others? With today's refactoring tools, my experience is that its quite painless to switch to a method call rather than a direct member access if that were necessary.

The other thing I would point out is that usually, in the case you mention, you would have to change the method name if you wanted to adhere to the principle of least surprise.

Let's say for a user object, you did start with a getter to reference the user's name, and there were now quite a few references to "user.getFirstName()". Now let's say you got a new requirement to return the user's nickname, if available, rather than their legal first name. Well, if you update the getFirstName() method to do that, yes, you don't have to change code everywhere, but it would kind of suck since it is unexpected for getFirstName to sometimes return the nickname and sometimes return the legal first name.

If we were following good coding practices, what we actually need now is to change all those references from "getFirstName()" to some new method (like "getPreferredName()") instead, which, once again, is no different than if we had used a direct reference to begin with.

Collapse
 
elcotu profile image
Daniel Coturel

Hi Scott, thanks for your answer.

I intended to leave the option 2 as the "more adequate" because the other two are very, very smelly.

Option 2 is more addequate but I wasn't thinking in a case like the one you describe. That case is not a change of behaviour in the getter, but a change in the behaviour of the class. I was thinking in some other cases:

1) Let's say you start with a setter that only does this:

public void setLastName(String ln) {
this.lastName = ln;
}

But in the future, you want to keep track of the modified fields after last read of the database, so in the next update you can only set those fields.

So you add an array of "touched" fields and say, "ok, so when every field is touched by a setter I will add it to the array". Like this:

public void setLastName(String ln) {
this.setTouchedField("lastName");
this.lastName = ln;
}

If you didn't had the setter in the first place, then it would be a pain in the ass adding this behaviour.

2) Let's say you have an object composed of some other objects. Your constructor creates an instance of every each object. But at some point you realize that you want to initialize some of the objects not on parent constructor, but when it's needed. So you could do something like this:

public CustomObject getInstanceOfCustomObject() {
if (this.instanceOfCustomObject == null) {
this.instanceOfCustomObject = new CustomObject();
}
return(this.instanceOfCustomObject);
}

These are some examples I had in mind when I said that it is at some point good to have those getters and setters already coded, even if they are initially totally dumb implementations.

Saludos,

Thread Thread
 
scottshipp profile image
scottshipp

Thanks for the thoughtful questions Daniel! In both cases, I think its still worth asking if there's not some behavior that can be exposed publicly instead of just exposing data. It is easy (because there's so many programmers doing it) to think in terms of data classes being passed around to behavior classes. This is not object-oriented, though. It's a near-cousin to global variables and procedural code operating on those variables. The paper Jason C. McDonald posted in the comments here is a pretty good discussion of these issues.

Unfortunately, both of the examples you gave are going to be prone to concurrency issues that are more serious than the discussion of whether they use "get" style methods. For the second example, try switching to the Initialization-on-demand holder instead. As far as the fact that the method is named "getInstance()" I would not put this in the same category as the getters/setters described in this article. This is a static factory method.

For your example 1, I feel that using the decorator pattern to track the changes in a separate class might be a better approach since it would be a cleaner separation of responsibilities, and you could dynamically add the change-tracking capability only where its needed. OTOH, you don't want to make a whole separate class if its not needed. If you really need to be able to track changes everywhere, then keep it as you showed (but think about concurrency!).

In that case, it would still have a "getXXXX" method then, and I would not be opposed to that. That's why I wrote:

I'm convinced that getters and setters which just return a class member almost never make sense. But you might write something close to getter/setter functionality as long as you are actually doing something in that method.

Thread Thread
 
elcotu profile image
Daniel Coturel

Hi Scott,
Thanks for your answer. Now I understand a little more about the concept you are communicating.
Saludos,

Collapse
 
marlysson profile image
Marlysson Silva

Awesome approach and good arguments.

I don't know if you knows the "jsf" ( web programming in java ) , that some specific classes that requires the getters and setters ( convention over configuration ) to their internal implementations uses all structure of the application that use some implementation.

Do you know some advice about it? Or isn't related to the post and there aren't to do?

Collapse
 
scottshipp profile image
scottshipp

I think I should have tackled this in the article. You are going to be on the hook to use getters and setters for libraries (like JSF) that reflect on them. Can't really avoid that.

But you can avoid a dangerous anti-pattern (in my opinion), which is then passing such objects around inside the application.

Usually, Java libraries that use reflection on getters and setters are doing it to bind data to/from these objects. There is usually a specific intent behind this, such as to create a POJO from incoming data, such as from the JSON body of an http request.

I believe that this type of automatic object creation should be limited to a single place at the edge of the application. If the usual pattern is followed of turning around and passing the resulting object around inside the app, it creates a situation where changes in the JSON body (or whatever it is), makes you have to change all the code paths that the object travels across.

So its best if you can isolate and decouple these auto-generated objects from your application. Build walls around them and keep them at the edges.

Collapse
 
aminmansuri profile image
hidden_dude

There are ways around getters/setters/properties but they aren't very simple. Like using a visitor pattern or renderers. They definitely aren't popular and would confuse the average programmer.

For some things getters/setters, while not real OO, are a good solution. For example the way Hibernate handles DB properties, or ActiveRecord. As long as people remember to wrap these with real objects later that expose behavior instead of attibutes.

Collapse
 
hussainakbar profile image
Hussain Akbar

(Darned cat walked over the keyboard and wiped my text)

I find Java programmers to be of the same cloth as Linux users; swearing by purity instead of concentrating on substance.

Case in point is the final declaration. It's my code. If I want to change a variable, I will. If not, not. So why use final?

This (and a boatload of similar posts) are because Java does have properties (public variables) but doesn't have any actual getters and setters. They're coincidental public methods that happen to set / read values of private variables.

I mean, just look at constructors that set multiple variables. Similarly, you can have a function for example:
public void setPerson(name, age, mobileNumber){...}

And another for:
public void setPersonAddresses(homeAddress, workAddress){...}

and not have individual setters for the above 5 variables. So, are they setters? They do the same work and the result is exactly the same. You can check for invalid values, copy arrays, etc. But, noooooo. Java purists would never deign to use them.

Now, have a look at DotNet. A VB.Net class would be:

Class Example
    Private _count As Integer

    Public Property Number() As Integer
        Get
            Return _count
        End Get
        Set(ByVal value As Integer)
            _count = value
        End Set
    End Property
End Class


`

That's a setter that's bound / fixed / glued to the property. You just use example.number = x and all the checks are carried out.

You get the ease of use with the needed functionality.

Purists: Go ahead and scream at me all you want. At the end of the day, Java still won't have any getters or setters.

Collapse
 
scottshipp profile image
scottshipp

It just sounds like you have your own brand of C# purism. In Java, the tools are there if you want to use them. "Final" keyword provides one ingredient towards immutable objects. The C# equivalent is the readonly keyword. If you want to use it, great, but if you don't, also great. I don't see anything to debate or any reason to compete Java against C#. Both have getters and setters, but different syntax for achieving the same result. C# properties are a little more compact and readable IMO which is nice. But Java is not missing anything.

Collapse
 
aminmansuri profile image
hidden_dude

Getters and setters often violate the principle of encapsulation which is to NOT expose internal details of your class.

They aren't really an OO technique but rather a "construction by parts" technique popularized by UI oriented techniques from VB or PowerBuilder. They are designed so that automated UI tools can get and set attributes of a UI component like color, size, etc.. It was later used for "JavaBeans" (that also started in the UI) and then was used by frameworks like Hibernate.

But to suggest this is good OO is just because many people never saw real OO from the Smalltalk days.
If you have something like a Car with a getX() and getY() position then you set the x and y position you are overriding whatever animation sequence that car should do when you "drive to" a position. A Car should really drive to positions not simply jump across the screen.

Methods should encapsulate BEHAVIOR not simple data mutation. That being said, there is room for objects such as value objects to pass around.

Another phenomena that is becoming apparent is that in backend Web programming many of the techniques used today are not really where OO shines. OO shines more in GUI and front end designs where you have inheritance and composition between components.

So I have to agree with the article.

Collapse
 
pinotattari profile image
Riccardo Bernardini

I agree. I think that you should decide the method of your class on the basis of what you expect that class to do (in an abstract sense), rather than on the basis of its internal structure. My personal experience (but YMMV) is that most of the cases (note: not all) where you are tempted to use a setter can be solved with suitable constructor to set the attribute once for all when the object comes to life.

Usually my approach (I use Ada, not Java, so the jargon will be slightly different) is to initially define the internal structure of the object as a "null record," with no field at all. In the spec file then I write the methods I think I need, possibly trying to compile the rest of the code against that spec. Of course, I am not going to obtain an executable, but I can check if the API of my object is complete. Successively, I begin working on the implementation (and this includes the fields of the class).
Usually with this approach any getters/setters you end up with make sense since they do not start from the implementation, but from an abstract view of the object and they are getters/setters "by accident," just because their implementation boils down to reading/writing a field. The resulting code will naturally pass the "acid test" named in one of the linked article why getters and setters method are evil

Can you make massive changes to a class definition—even throw out the whole thing and replace it with a completely different implementation—without impacting any of the code that uses that class's objects?

Collapse
 
magmax profile image
Miguel Ángel García

I see you had two different problems here: The important one, you found a getter returning a pointer, what means you have the control over the content. Aditionally, you put the blame on the getters and setters.

The feature I hate most about Java are equals, getters and setters. They are harder to read (car.setEngine(engine) against car.engine=engine) and harder to write, even with IDEs help, because I need to be generating them and maintaining them if I decide to change the variable name.

They require more code, so when I open the class I have to read those methods just to be sure they are not doing anything more than an assignment. This is time.

And all of this, as you said, to override one in a million.

I found a library, lombok (projectlombok.org/features/GetterS...), that helps you to avoid the implementations with annotations. It is true that it still require to use .getFoo and .setFoo, but I avoid generating them from the IDE and maintain them.

Anyways, I miss a feature in Java like Python's properties, that allow you to override just that method in a million:

class Foo:
    def __int__(self):
        bar = None    # normal public var
        _bazz = None  # private var to be used as property

    def getBazz(self):
        return _bazz

    def setBazz(self, value):
        self._bazz = 2 * value

    bazz = property(getBazz, setBazz)  # property declaration

foo = Foo()
foo.bar = 5
foo.bazz = 10
print(foo.bar)
print(foo.bazz)

So, you can change any public variable to a property just when you require to override that method.

Collapse
 
shaaza profile image
shaaza • Edited

Exactly! Embrace (almost) complete immutability, program with expressions, isolate mutation to a corner of your system, and you can start focusing on the problem at hand instead of orthogonal issues such as this.

It's so much easier to change software when you can read code without the mental overhead of tracking state through time. I know people who have gone back to writing OO languages but still don't let go of the ideas encompassed by the functional paradigm, and it often works out well for many cases.

For a deeper (and a level-headed) understanding of the benefits of FP and what to take away from it, I recommend the paper "Out of the Tar Pit", if folks haven't already it. github.com/papers-we-love/papers-w...

Collapse
 
smontiel profile image
Salvador Montiel • Edited

You made me think!

Great post!

Collapse
 
bgadrian profile image
Adrian B.G.

At the begining I was ..."I hope he doesn't suggest to expose the variables", then

My "default" is to start with a private final member, set only by the constructor. No getter or setter!
Ok, we're all good, move on.

I agree that in most of the cases no variables should be exposes, in any matter, it is a statement of: "please side effects and bug, come and get me". In some env it makes sense because 99% of the time is about public vars (for example in Unity3d you have components, and you need to expose parameters of all sort so the game devs can visually instatiante and configure the instances, and ofc this leads to other big issues, beside the ones mentioned here).

Collapse
 
hack2root profile image
Artur Mustafin • Edited

It so naive for you to misunderstanding how getters and setters work;

The reality is that getters/setters have at least exactly the same security as of any over accessor modifiers.

Moreover, getters/setter have more security other the items thy control when geclared properly.

Getter/Setter is an abstracton of control, allowing you to make some additional operations before you get into trouble with references you incapsulated class data outside of a class.

For examle, SIMPLY buuld and return a COPY of data when getter called, when needed, or clone data when setter called. It is that simple

Collapse
 
rossdrew profile image
Ross • Edited

This seems to me like a list of cases of using something badly, then complaining they are dangerous. No, using things dangerously is dangerous. No awareness of mutable state of members (returning mutable lists of restricted data), no awareness of future proofing (space for future validation without changing APIs for example)...these are not problems with the feature, but with the user.

Collapse
 
kolyaio profile image
Nikolai Ilushko

I think the title is a bit problematic because you trying not to use getters and setters at every single moment just because we were taught to use them. At the end the message is to create real isolation between different parts of the code you do instead of doing setters and getters as check mark for OOP "requirements".

Collapse
 
lukbenda profile image
Lukas benzin Benda

And interface and inheritance and proxy for AOP you newer see? Yes I see a lot of project where was same stupid developers and the harm which they do was prity expensive. Mainly see in a lot of copy paste or repetitive work, because inheritance and interface coldn't be reasonable use.

Collapse
 
rodislavable profile image
Rodislav Moldovan

The article should be named: avoid auto-generation of getters and setters, (because it can cause free mutability issues on a plain field).
And has nothing to do with getters and setters in general.

Just fix the title and article will start to make way more sense, we all know - naming is the most difficult problem.

Collapse
 
coderangshuman profile image
Angshuman Halder

This post was amazing. It changed my perspective towards getters and setters.
Having getters and setters makes no sense only if it exposes the private members of the class for being manipulated by other classes.

Collapse
 
xtabdeveloping profile image
Márton Kardos • Edited

Yeah, one of my friend does this thing constantly in Scala, where basically all the fields he creates are immutable val-s. So there exists an immutable field, as well as a getter for it, which doesn't make sense at all, especially because the functional approach implies, that an immutable variable is basically the same as a constant function.

Collapse
 
theomails profile image
Theodore Ravindranath • Edited

I think within the code base of a single self contained application, you can just start with public variables. It's not difficult to refactor and add indirection later.

But if you are sharing a jar which is going to be is used by another team, then better expose via getters and setters so that there is some wiggle room to alter the implementation. Also, in such case it would have to be done with interface in the first place so public fields are out.

There is a distinction here to be made between just any Java public class and something that is module-public (something that you would expect outside teams to use)

Collapse
 
nallack profile image
cgray

You should never write public variables for a class in object-oriented programming.

  • You are exposing internal state, thus making it easy for someone put your class into an invalid state, it is now impossible for the class to determine if and when it is being put into an invalid state, and is why poorly designed software breaks.
  • Your class may need to perform extra functionality or provide a view of an implementing instance on a call to an accessor or mutator. You don't want to waste time swapping over instead of writing it the correct way to begin with.
  • You cannot provide an interface to public member variables, thus is not ideal to use when writing a library because the API layer can't provide access to everything needed to use your class anymore.
  • Engineers have spent thousands of hours incorporating accessors and mutators into languages to encourage their use for these reasons.

(However, in "some cases" a struct can be more suitable than a class (as seen in math libraries) where member variables should instead always be public. The only limitation you have for writing a struct is that all variables are also invariant. Some languages also don't have structs (e.g. Java), in which case you need to use a class to create a struct-like object that has no responsibility for preventing invalid state e.g. java.awt.Point has public x and y members. An awt ui object however will never return its internal state, accessors will always return a clone of an internal Point instance.)

Collapse
 
amihaiemil profile image
Mihai A.

I'm happy to see that more people are avoiding getters and setters. But this is such a long wall of text and all of it can be sumarized into one simple idea: "model objects" (get/set JavaBeans) are not real objects!

They are lifeless toys, which we have to move ourselves, instead of relying on them to move and do the job for us. Model objects should not exist in an object oriented world at all. Here is a metaphor about it:

amihaiemil.com/2018/04/17/dolls-an...

Collapse
 
dstefanow profile image
Dobromir Stefanov

What we have to use if we want validation for the current field only in the class?
... Yes we use setters!

These examples are not correct and don't give a logical answer to the question why we shouldn't use getters and setters.

Collapse
 
scottshipp profile image
scottshipp

Hi Dobromir! I mentioned the case of validation in a setter as a valid usage, in the section "When getters make sense"

In a setter, before updating the state in this object according to some input, we validate the input.

Nevertheless, a key point that shouldn't be overlooked is to prefer to make validation part of a behavior rather than part of a setter. For example, let's say a web site has a place where potential customers can enter their name and email address to request more information. When someone enters their information in the form and submits it, we want to perform a number of actions including but not limited to:

  • Validate the email address
  • Save the email address along with other data like the current date and time
  • Kick off an automated email which has more information for the customer
  • Schedule a follow up email for a couple days from now to remind the customer about the product

A common approach is that once the web server receives the request, an object called Customer or User is created with name and email fields. The object is passed around the application and the name, email, and other fields are constantly gotten and set. For example the first thing that may happen is a database lookup which indicates we already have other information for this person, and those fields are all set on the existing object.

Well, whether or not the validation of the email happens in this object, and whether or not it happens in the constructor or setter, I think this data-centered approach is fundamentally flawed. Consider the case where we change what data we collect. Instead of name and email, now we're going to do it with name and cell phone and we're going to use SMS messaging to interact with the customer, because SMS has eight times the response rate of email (retaildive.com/ex/mobilecommerceda...).

In this scenario, we switched from email to phone, and now we go refactor every place in the application that calls getEmail() or setEmail().

Instead, what if we took behavior as the first-class citizen of this scenario. What behavior do we want to happen when the customer submits their data? We want to give them more information. OK. We make an interface PotentialCustomer with a giveMoreInformation() method. (Sidebar: the naming here could use some work probably). We implement this interface for our name and email scenario.

When the web server receives this data, it creates the instance of our implementation of PotentialCustomer. The name and email data is passed to PotentialCustomer via the implementation's constructor, and this data is private and immutable so the rest of our application doesn't even know (or care) that we're using name and email.

The PotentialCustomer is composed of other members, who are themselves behavioral objects, and each have a task. One persists the data. Another sends the initial email. Another schedules the follow-up. All of this is called when giveMoreInformation() is invoked.

Now we have a much better situation for the update to use SMS instead of email. The worst case here is that we create a new implementation of the PotentialCustomer interface for this scenario. We don't need to refactor code across many paths.

Does that makes better sense?

Collapse
 
javasavvydev profile image
javasavvydev • Edited

Don't you use inheritance with java and OOP? Creating public variables instead of access methods can cause problems down the road, it also can lead to unexpected behavior. See the example below. While you probably wouldn't have a getter for a public variable, they are public for this demonstration of showing the difference. Remember, the highest cost of software is not the initial released product, but maintaining it!

public abstract class Animal {
public String name = "animal";
public String getName() { return this.name; }
}

public class Cat extends Animal {
public String name = "KIT-CAT";
}

public class PlayWithAnimal {
public static void main (String [] args) {
Animal animal1 = new Cat();
Cat cat = new Cat();
System.out.println(animal1.name);
System.out.println(animal1.getName());
System.out.println(cat.name);
System.out.println(cat.getName());

}
}

Output: animal, KIT-CAT, KIT-CAT, KIT-CAT
So now Inheritance is less useful. You can create an animal instance that contains a cat, but without a getter method you are now unable to access the cat's name...

It's also much easier to find "usages" of methods in most IDE's when using getters and setters. This can be very useful and powerful when refactoring code. (I have had to refactor code that didn't use getters and setters and it was more painful...

Some of the examples are just bad code practices, like the ability to add debts to the list, in this case it would be better to pass a copy as you said, that does not really have anything to do with getters and setters being bad, you would have the same problem with a public variable, but it COULD be protected through a getter method returning a copy.

Collapse
 
bonobomagno profile image
Orland

This is just bad code example. In a real work case, you will check this.prefix before overriding it. Or better, Only getName with output name+prefix.
There is really no sense making a double setter with only one setter function. Particularly if the setter function name don't explain this.
If you really want to do it in this way, you will add a second argument on the setName with a default Junior value for easy overriding the default.

But again, this problems don't exist in other languages.

Collapse
 
voins profile image
Alexey Voinov

Yeah! 100% agree.

Collapse
 
niorad profile image
Antonio Radovcic

Thanks for this! You should check out Casey Muratori's epic rant on getters/setters. He's a bit more direct but the message ist mostly the same:
youtube.com/watch?v=_xLgr6Ng4qQ

Collapse
 
scottshipp profile image
scottshipp

I love it!

Collapse
 
anothererk profile image
Cristian

Do you really remember the encapsulation concept?

Collapse
 
gustavoagt profile image
Gustavo Gómez

So, if want to change the implementation later of the reference: "public Engine engine"? but 100,000 other classes have directly access, what do you recommend to do?

if before to get a value i need to make some validation, what do you recommend me to do?

Collapse
 
scottshipp profile image
scottshipp

Sorry if it wasn't clear. First, I would recommend not making it public to begin with, and definitely not for 100,000 other classes to have access. If you need to make some validation before getting the value, definitely keep the variable private and expose a well-named method instead.

Collapse
 
courier10pt profile image
Bob van Hoove

I've seen quite a couple of articles warning against 'typical' getters and setters usage. What I really appreciate is the nuance you put in explaining when they are appropriate to use.

Collapse
 
schrammel profile image
Schrammel

First read about the law of demeter and about SOLID, after understanding already can erase the article.

Collapse
 
scottshipp profile image
scottshipp

What do you have in mind exactly? Getters and setters can violate both the Law of Demeter and SOLID principles. The Interface Segregation Principle, which is the I in SOLID, states that no client should be forced to depend on methods it does not use. A bunch of extra methods that expose a class' data are often methods that clients shouldn't depend on.

As for the law of demeter, a getter is actually a classic and oft-cited example of demeter violation. Let's say you have an ecommerce site and its time for the customer to pay for the order. In the violation example, you take the customer's wallet (customer.getWallet()) and then you subtract the money out of it (wallet.deduct(orderAmount)). Picture this as a transaction in real life. You ask the customer to pay, they hand you their entire wallet and you reach in. This is meant to illustrate the need for the Law of Demeter. Google "law of demeter wallet" and you'll see what I mean.

Collapse
 
schrammel profile image
Schrammel

About SOLID:

In my opinion, by using a getter you can only break "Interface Segregation" if you break the "Liskov Substitution"

About LAW OF DEMETER:

the correct thing is that the customer makes the payment, and keep it for him, after all, it is not the wallet that pays, but the customer.

Code:
Custumer.deduct (orderAmount)


You said right at the beginning of the article.

"Now, I want to point out that there is no meaningful functional difference between that class, a public class with a public class member, and the following class, a public class with a private member that is exposed by getters and setters."

But I say:

Imagine that you use this code in 10 locations

car1.engine = new HemiEngine();

Now you need to enter a validation when changing the engine of the car. you will have to change the code in several places because you broke Demeter's law.

About changing engine properties

  • Single Responsibility: Ideally a class would encapsulate a property change, without getters there is no way to use a logic injected into the constructor
  • Integrity, with getters you can return a copy of the values ​​of your engine. Both of these reasons force you not to create public fields.
Collapse
 
hohonuuli profile image
Brian Schlining

tl;dr: Getters/Setters aren't evil. They are a tool.

Good lord, that's an awful title. People are going to only read that and think" I shouldn't use getters/setters". Please don't follow that advice. I would argue that in Java, NEVER, NEVER, NEVER access a public field of an instance. Always go through an accessor method. Accessors/mutators also can be defined in interfaces, allowing your software to enforce code contracts.

So yes, if you don't need to expose a field, don't. If you can make field immutable, that's great!! But still use an accessor to get it.

Collapse
 
itscorey profile image
Lucas

Which theme is that in the first image?

Collapse
 
scottshipp profile image
scottshipp

It's great isn't it? That's the "Material Theme UI" plugin. You have to install it through the Plugin Repository. Here's the link: plugins.jetbrains.com/plugin/8006-...

Collapse
 
ethernet profile image
ethernet

Thanks for the post. Pretty clearly & I need a rafactor in my entites.

Collapse
 
chastings77 profile image
CASEY HASTINGS
Collapse
 
louissaglio profile image
Louis-Saglio

Its why Python don't have keywords like public or private.

Collapse
 
yuricoco profile image
yuricoco

good point of view. I taught about that for a moment and after reading your article I've the conviction of the right way to use getter and setter :)

Collapse
 
smailg profile image
SmailG

I really found useful posts here... This is not one of them

Collapse
 
cscbnguyen43 profile image
Binh Thanh Nguyen

Thanks, nice article.

Collapse
 
omrerdn profile image
Ömer Erden

It's possible to wrap your private list with an UnmodifiableList when getting it into public. This will not give compile time error though but the wrapping will make it safer.

Collapse
 
followchefs profile image
Foodtw!tter^com

who cares how nice is looking your baby, if it does not get born? The core is a product that must start breathing and living, the rest of this crap can be re-factored later on.

Collapse
 
thisisgiorgio profile image
Giorgio Martini

mobx uses getters and setters.. should I avoid it then?