201

Getters and setters are often criticized as being not proper OO. On the other hand, most OO code I've seen has extensive getters and setters.

When are getters and setters justified? Do you try to avoid using them? Are they overused in general?

If your favorite language has properties (mine does) then such things are also considered getters and setters for this question. They are the same thing from an OO methodology perspective. They just have nicer syntax.

Sources for Getter/Setter Criticism (some taken from comments to give them better visibility):

To state the criticism simply: Getters and Setters allow you to manipulate the internal state of objects from outside of the object. This violates encapsulation. Only the object itself should care about its internal state.

And an example
Procedural version of code:

struct Fridge
{
    int cheese;
}

void go_shopping(Fridge fridge)
{
     fridge.cheese += 5;
}

Mutator version of code:

class Fridge
{
     int cheese;
      
     void set_cheese(int _cheese) { cheese = _cheese; }
     int get_cheese() { return cheese; }
 }

void go_shopping(Fridge fridge)
{
     fridge.set_cheese(fridge.get_cheese() + 5);        
}

The getters and setters made the code much more complicated without affording proper encapsulation. Because the internal state is accessible to other objects we don't gain a whole lot by adding these getters and setters.

The question has been previously discussed on Stack Overflow:

Milan
  • 117
  • 1
  • 4
Winston Ewert
  • 24,732
  • 12
  • 72
  • 103
  • 24
    `Getters and setters are often criticized as being not proper OO` - Citation, please. – Robert Harvey Nov 26 '10 at 22:43
  • 37
    @Robert Harvey: http://typicalprogrammer.com/?p=23 | http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html | http://www.darronschall.com/weblog/2005/03/no-brain-getter-and-setters.cfm | http://www.adam-bien.com/roller/abien/entry/encapsulation_violation_with_getters_and – greyfade Nov 26 '10 at 22:53
  • 46
    @Job, why because it has code? It's a good question and reeks of holy war if taken seriously. – Peter Turner Nov 26 '10 at 23:55
  • 1
    The code doesn't even make sense, why is set_cheese() using += – alternative Apr 10 '11 at 17:09
  • @mathepic, good catch. That was a typo. Now I see why I need unit tests. – Winston Ewert Apr 10 '11 at 17:35
  • @Winston Ewert better is for the language to easily support such constructs, like ruby or C# does. I especially like ruby's metaprogramming creation of getters/setters that make unit tests pretty useless for just testing getting/setting (certainly they are useful for other things) – alternative Apr 10 '11 at 18:44
  • 1
    @mathepic, yes its better when the language has cleaner support. But the question is if you should be accessing the data inside the class at all. – Winston Ewert Apr 11 '11 at 02:36
  • @Winston Ewert of course you should, if you couldn't access any data then the class is useless. However obviously you shouldn't be able to access all its data, just what is crucial to the client. If the client has to work with the data it gets back, then its not crucial and should be abstracted. – alternative Apr 11 '11 at 19:48
  • 1
    @mathepic, right. It's just that a lot of people use getters/setters to manipulate data inside objects when they should be abstracting. – Winston Ewert Apr 11 '11 at 21:53
  • @Winston Ewert I think a lot of the problem occurs due to libraries - they can't possible provide every function you might need so they often have to have setters and getters. Languages that don't support inheriting protectedly make this far worse. – alternative Apr 11 '11 at 23:23
  • @mathepic, I hadn't thought of that but yeah. – Winston Ewert Apr 11 '11 at 23:47
  • 4
    @Winston Ewert: "... the question is if you should be accessing the data inside the class at all.": well, noone forces you to implement getters and setters for all member variables, you only implement those you need. That's why you use getters and setters instead of public member variables. – Giorgio Nov 19 '11 at 14:07
  • 1
    @Giorgio, of course nobody is forcing you. The problem is that many people automatically implement getters and setters for every member variable and then access them just like if they had been public. – Winston Ewert Nov 19 '11 at 15:39
  • 3
    @Winston Ewert: I do not see how the absence of getters / setters would solve this problem: there must be a way to access every piece of data otherwise it is useless; it is the task of a good design to decide which part of the data is accessible to which part of the code. If one is a bad designer he or she will be such with or without getters and setters. Just my 2 cents. – Giorgio Nov 19 '11 at 16:55
  • @Giorgio, I'm claiming that you should never have getters and setters, that's why the question is titled "when are Getters and Setters justified." I do claim that getters and setters are overused, because many programmers have failed to grasp the concept of data hiding and think that getters/setters provide it. – Winston Ewert Nov 19 '11 at 18:37
  • 2
    Try not using them at all. See what happens. IMO, critical thought happens. DTO? Nah. Data object wrapper that knows how to map itself, how to update itself in the DB, etc... with a basic generic data structure at the core. That's a lot more appealing to me than contemporary accepted thought on the matter. – Erik Reppen Jun 22 '13 at 06:08
  • 1
    Here is a citation for the question: http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html – Josh Nov 26 '10 at 22:52
  • 1
    I realize this is an old post, but I have to comment. I'm seeing a lot of getters and setters in some Java code I've recently been asked to review. I don't have much experience with Java, so I wanted to verify whether it was a better programming practice than I thought. I believe the accepted answer has a flaw. We don't have to add a `setSalary()` method. Instead, we should have something like: public void acceptNewJob(Job newJob) { salary = newJob.getSalary(); } This way the salary is set from an object that makes sense, instead of any old piece of code. That's my 2 cents. – dbc60 Nov 22 '13 at 20:29
  • @Job — Programmers.SE is the perfect site for this question. It doesn't belong on SO because it's not a specific problem with a specific solution; it's more of a general coding style/architecture problem. Even if it does tend to bring up debate. – chharvey Jul 15 '15 at 17:59
  • "you only implement those you need. That's why you use getters and setters instead of public member variables." -- There's no design difference between public setters and public member variables ... you can make member variables public only as needed. Both are poor design for the same reason globals are bad designe -- because control of the value of the property is not localized. Use immutable objects instead -- their properties are only set at time of construction. – Jim Balter Jul 27 '15 at 21:08
  • I'm wondering if there is value in adding a getter and setter for a static field in java. Just had a code review where this was done and it stood out a little. Guess I'm not used to seeing that. – simgineer Mar 10 '21 at 23:33
  • @simgineer I'd avoid static mutable fields in the first place as undesirable global state. But if you have them I'd treat them the same as fields on objects. – Winston Ewert Mar 12 '21 at 15:27

13 Answers13

181

Having getters and setters does not in itself break encapsulation. What does break encapsulation is automatically adding a getter and a setter for every data member (every field, in java lingo), without giving it any thought. While this is better than making all data members public, it is only a small step away.

The point of encapsulation is not that you should not be able to know or to change the object's state from outside the object, but that you should have a reasonable policy for doing it.

  • Some data members may be entirely internal to the object, and should have neither getters nor setters.

  • Some data members should be read-only, so they may need getters but not setters.

  • Some data members may need to be kept consistent with each other. In such a case you would not provide a setter for each one, but a single method for setting them at the same time, so that you can check the values for consistency.

  • Some data members may only need to be changed in a certain way, such as incremented or decremented by a fixed amount. In this case, you would provide an increment() and/or decrement() method, rather than a setter.

  • Yet others may actually need to be read-write, and would have both a getter and a setter.

Consider an example of a class Person. Let's say a person has a name, a social security number, and an age. Let's say that we do not allow people to ever change their names or social security numbers. However, the person's age should be incremented by 1 every year. In this case, you would provide a constructor that would initialize the name and the SSN to the given values, and which would initialize the age to 0. You would also provide a method incrementAge(), which would increase the age by 1. You would also provide getters for all three. No setters are required in this case.

In this design you allow the state of the object to be inspected from outside the class, and you allow it to be changed from outside the class. However, you do not allow the state to be changed arbitrarily. There is a policy, which effectively states that the name and the SSN cannot be changed at all, and that the age can be incremented by 1 year at a time.

Now let's say a person also has a salary. And people can change jobs at will, which means their salary will also change. To model this situation we have no other way but to provide a setSalary() method! Allowing the salary to be changed at will is a perfectly reasonable policy in this case.

By the way, in your example, I would give the class Fridge the putCheese() and takeCheese() methods, instead of get_cheese() and set_cheese(). Then you would still have encapsulation.


public class Fridge {
  private List objects;
  private Date warranty;

  /** How the warranty is stored internally is a detail. */
  public Fridge( Date warranty ) {
    // The Fridge can set its internal warranty, but it is not re-exposed.
    setWarranty( warranty );
  }

  /** Doesn't expose how the fridge knows it is empty. */
  public boolean isEmpty() {
    return getObjects().isEmpty();
  }

  /** When the fridge has no more room... */
  public boolean isFull() {
  }

  /** Answers whether the given object will fit. */
  public boolean canStore( Object o ) {
    boolean result = false;

    // Clients may not ask how much room remains in the fridge.
    if( o instanceof PhysicalObject ) {
      PhysicalObject po = (PhysicalObject)o;

      // How the fridge determines its remaining usable volume is a detail.
      // How a physical object determines whether it fits within a specified
      // volume is also a detail.
      result = po.isEnclosedBy( getUsableVolume() );
    }

     return result;
  }

  /** Doesn't expose how the fridge knows its warranty has expired. */
  public boolean isPastWarranty() {
    return getWarranty().before( new Date() );
  }

  /** Doesn't expose how objects are stored in the fridge. */
  public synchronized void store( Object o ) {
    validateExpiration( o );

    // Can the object fit?
    if( canStore( o ) ) {
      getObjects().add( o );
    }
    else {
      throw FridgeFullException( o );
    }
  }

  /** Doesn't expose how objects are removed from the fridge. */
  public synchronized void remove( Object o ) {
    if( !getObjects().contains( o ) ) {
      throw new ObjectNotFoundException( o );
    }

    getObjects().remove( o );

    validateExpiration( o );
  }

  /** Lazily initialized list, an implementation detail. */
  private synchronized List getObjects() {
    if( this.list == null ) { this.list = new List(); }
    return this.list;
  }

  /** How object expiration is determined is also a detail. */
  private void validateExpiration( Object o ) {
    // Objects can answer whether they have gone past a given
    // expiration date. How each object "knows" it has expired
    // is a detail. The Fridge might use a scanner and
    // items might have embedded RFID chips. It's a detail hidden
    // by proper encapsulation.
    if( o implements Expires && ((Expires)o).expiresBefore( today ) ) {
      throw new ExpiredObjectException( o );
    }
  }

  /** This creates a copy of the warranty for immutability purposes. */
  private void setWarranty( Date warranty ) {
    assert warranty != null;
    this.warranty = new Date( warranty.getTime() )
  }
}
Dima
  • 11,822
  • 3
  • 46
  • 49
  • 4
    Please don't take my Fridge example too seriously. :) A real fridge ought to be a container object, I'd expect it to know how to hold objects without worrying about what exactly they were. I.E. it would be like an ArrayList. As for what makes it a Fridge, let's say it serializes objects to disk when stored so that they will survive system failure. Ok. Enough taking my fridge example over seriously. – Winston Ewert Nov 26 '10 at 23:40
  • 1
    On the contrary, I think a smart fridge should know what it contains and how much. This way, if you call `takeCheese()` and there is no cheese left, the fridge would throw an exception. :) The point is that you want to create abstractions, and the class interface is what lets you do that. So you want your interface to represent the things you want your object to do, not its internal structure. Sometimes the two are essentially the same, but more often they are not. – Dima Nov 26 '10 at 23:47
  • oh, the fridge knows what it contains. But it doesn't understand the nature of what it contains. The interface would be something like take(Cheese, 5) to remove 5 units of cheese from the fridge. The fridge has no knowledge of actual cheese, milk, or anything else. It just stores what is put into it. – Winston Ewert Nov 27 '10 at 00:02
  • 6
    But shouldn't the fridge know the expiration dates, so that it can tell you that the cheese has gone bad and should be thrown out? :) Ok, we have to stop this! :) – Dima Nov 27 '10 at 00:10
  • 10
    Quite an interesting discussion of [Fridge Logic](http://tvtropes.org/pmwiki/pmwiki.php/Main/FridgeLogic) you've got going on here... – Mason Wheeler Nov 27 '10 at 06:27
  • 35
    Haha, I'd like to see the ad for that: **"It's a brand new kind of fridge: It throws things at you when trying to grab something that isn't there! This way you will only try that once! You worry about stuffing the fridge, and let the fridge worry about illegal behaviour!"** – gablin Nov 27 '10 at 09:13
  • 4
    +1 This explanantion is better than any I found in books. – Oliver Weiler Apr 11 '11 at 07:40
  • Ah, but what happens when the person's data is just wrong. The customer calls up and says "you've enterd my age incorrectly, it says I'm 76 when I'm actually 22". Suddenly you have to tell them to get used to it, or whip out an SQL editor and directly modify the DB. However, I understand what you're saying - getters and setters are bad; give an object methods that perform defined actions on it. – gbjbaanb Aug 04 '11 at 14:08
  • @gbjbaanb, this really depends on how the whole system is implemented. Maybe there is a class called PersonParams, which is plain old data with public fields or getters/setters for everything, and it is this object that is used to initialize Person. Or maybe you just delete the person's record and create a new one. This is not the point. And no, I am not saying that getters/setters are bad. I am saying that you need to look at your class and decide which data members should be read-only, which should be read-write, and which should be completely hidden. – Dima Aug 04 '11 at 14:20
  • @gablin: Beware http://cs.nyu.edu/~jml414/ui/assign3/smart_refrig.html ! – Matthieu M. Oct 03 '11 at 18:09
  • "By the way, in your example, I would give the class Fridge the putCheese() and takeCheese() methods, instead of get_cheese() and set_cheese(). Then you would still have encapsulation." This explains a lot! Credits should be shared between you both as, Winston Ewert : For putting it as get_cheese() and set_cheese() Dima : For putCheese() and takeCheese() Before I came here I went through http://programmers.stackexchange.com/questions/187886/how-important-is-encapsulation/187894#187894 and after reading this part of your answer, I understood most of the things there were in that answer too. – Chathura Kulasinghe May 19 '14 at 21:41
  • 50
    The example has it all wrong. There should not be an Age field nor a setAge() method. Age is a function of the Person birthDate as compared to some point in time. While seemingly trivial, this is exactly what is wrong with the modern practice of full mutability of objects and other bad designs, as seen by get/set methods for private fields versus carefully considering what is really mutable, what is a field, what the object should know about its behaviors and what state changes are actually valid (which setX methods completely destroy). – Darrell Teague Jul 21 '14 at 18:49
  • 3
    +1. But for the salary, shouldn't the job be its own object, complete with its own salary field, and shouldn't the person's salary be determined by the salary field inside of their job object? – Panzercrisis Sep 08 '14 at 12:50
  • 3
    +1 for Darrell and getting the underlying design right to minimise the need for mutability. Of course one may be hamstrung by a poor database design and "just make it work, now" attitudes from above... – Julia Hayward Sep 08 '14 at 13:57
  • what about having no getter and setter for some variables, and having them public, does that "break encapsulation" and does it matter? – barlop Feb 01 '15 at 04:12
  • 1
    Yes, public data members do break encapsulation, and are generally a bad idea, because they create tight coupling between classes. Getters and setters provide a better degree of separation between the implementation and the interface of your class, and give you more wiggle room to change the implementation without changing the interface. – Dima Feb 02 '15 at 13:34
  • 4
    "Having getters and setters does not in itself break encapsulation. What does break encapsulation is having a getter and a setter for every data member (every field, in java lingo)." -- This is obviously nonsense; the percentage of an object's properties that are externally changeable has no bearing on whether encapsulation is broken. The plain fact is that public setters break encapsulation of the *value* of the property ... any piece of code anywhere can change it at any time. Darrell Teague gets it right ... public setters are bad design. – Jim Balter Jul 27 '15 at 21:12
  • All I get from that and your answer is that you don't understand the concept of encapsulation. it also contradicts your *assertion* that "Having getters and setters does not in itself break encapsulation". That claim is quite different from "they only break encapsulation a little if you only have a few of them". Again, Darrell Teague got it right. You have no response to that because of your lack of expertise in this area. – Jim Balter Jul 28 '15 at 00:56
  • Immutability is not the arbiter of good design. The reason Age shouldn't be a field has little to do with immutability and everything to do with avoiding a fragile, costly, and potentially bug-ridden nightmare going forward. While there is a correlation between immutability and good design in this case, correlation is not causation. Private fields may commonly be of no concern to the outside world, but that's by no means the only reason to make a field private. Contrary to what trendy Functional Programming purists say, merely changing state from outside doesn't violate encapsulation. – Syndog Mar 22 '18 at 22:11
  • @dave-jarvis Can you give some creditable citation for this, "What does break encapsulation is automatically adding a getter and a setter for every data member" as I am facing very hard time explaining this to the people and already been rejected from few interviews as more than half dev population defines encapsulation as creating getter setter of fields/member. Thanks – foxt7ot Mar 24 '18 at 11:35
  • @foxt7ot I learned this from "Effective C++" by Scott Meyers. Also, a word of advice: an interview is a bad time to argue about programming philosophy. – Dima Mar 24 '18 at 12:13
  • @Dima Thanks for citation and your valuable advice – foxt7ot Mar 24 '18 at 12:45
  • 1
    The salary example is misleading. In that case, the method should be `changeJob(newSalary)` or `getRaise(newSalary)`, etc. (with possible additional parameters). See [Cormac's answer](https://softwareengineering.stackexchange.com/a/255679/158474). – Utku Oct 16 '18 at 02:01
  • Well, "Age" isn't mutable with the current state of medical art, but it is "changing". All the time. – gnasher729 Oct 12 '21 at 18:04
46

The basic reason for getters and setters in Java is very simple:

  • You can only specify methods, not fields, in an interface.

Hence, if you want to allow a field to pass across the interface, you will need a reader and a writer method. These are traditionally called getX and setX for the field x.

  • 49
    That is a language limitation. The real question is whether we should be allowing other objects to manipulate that state. – Winston Ewert Nov 26 '10 at 23:05
  • @winston, I'm not sure that's a language limitation, that is the nature of an abstract class (or a Delphi Interface) common to lots of languages I think. – Peter Turner Nov 26 '10 at 23:52
  • 3
    @Peter Turner, clearly nothing prevents a language from having interfaces that include properties. Under the covers that may well be implemented as getter/setter but it would be easy enough to add support to interface definitions for properties. – Winston Ewert Nov 26 '10 at 23:54
  • 2
    @Winston, you will eventually need to allow classes to pass information back and forth between each other to actually get work done. What would you suggest instead? –  Nov 27 '10 at 06:38
  • 6
    An object is supposed to provide a higher level interface to it innards. Getters and Setters tend to be a low level interface. For example, suppose you have a class that implements a binary tree. You could have functions like GetLeft(), GetRight(), GetValue(), and GetKey() in order to navigate the tree. But that is the completely wrong approach. Your binary tree class should provide operations like Find, Insert, Delete. – Winston Ewert Nov 27 '10 at 14:51
  • 6
    To take another example, consider a tetris piece. The tetris piece has some internal state like block_type, rotation, position. You could have getters like GetBlockType(), GetRotation(), GetPosition(). But you really shouldn't. What you should have is a GetSquares() method which returns a list of all of the squares occupied by this piece. You also shouldn't have stuff like SetPosition() or SetRotation(). Instead, you should have operations like MoveLeft(), MoveRight(), Rotate(), Fall(). – Winston Ewert Nov 27 '10 at 14:55
  • 1
    So its not about refusing to pass information between objects or even not having methods named Get*/Set*. However, if you are providing access to all your object's innards to the entire world via getters and setters, it looks like your object is nothing but a data storage unit. Thus its not really an object. Instead, you should consider the higher level operations on the object. – Winston Ewert Nov 27 '10 at 14:58
  • @Winston, so you basically argue that "proper OO" does not allow getters and setters. How will you provide an interface to a data transfer object then? –  Aug 08 '11 at 06:51
  • 1
    @Thorbjørn Ravn Andersen, it's not an absolute. Higher level operations are to be preferred to Get/Set operations, but I don't know of any that could apply to a DTO. – Winston Ewert Aug 08 '11 at 15:49
  • @Winston, so your "An object is supposed to provide a higher level interface to its innards" is perhaps a bit too broad? –  Aug 08 '11 at 17:02
  • 1
    @Thorbjørn Ravn Andersen, it looks like I've got a typo in that. I meant to say that it is supposed to provide a *high-level* interface to its innards. That is, the interface to an object should be defined by the role of an object not the internal data members inside the object. A DTO is deliberately a dumb container of data fields, as a result getters and setters make sense they are the high-level interface for that field. – Winston Ewert Aug 08 '11 at 17:56
  • 1
    "How will you provide an interface to a data transfer object then? " -- Such objects should be immutable. – Jim Balter Jul 27 '15 at 21:18
  • Also DTOs probably shouldn't exist as they are in, say, Java. The structure of the object comes from the database anyway, so why are we re-stating all the fields in a transfer object, and then again in a mapping object? The language just doesn't have the concept of a "Data Object" built in, so we fake one out of code objects and use cumbersome libraries like Hibernate. – Bill K Jan 17 '20 at 17:26
25

From http://www.adam-bien.com/roller/abien/entry/encapsulation_violation_with_getters_and

JavaBean style:

connection.setUser("dukie");
connection.setPwd("duke");
connection.initialize();

OO-style:

connection.connect("dukie","duke");

Well, clearly I prefer the latter approach; it doesn't bleed implementation details, it's simpler and more concise, and all of the needed information is included with the method call, so it's easier to get it right. I also prefer setting private members using parameters in the constructor, whenever possible.

Your question is, when is a getter/setter justified? Perhaps when a mode change is needed, or you need to interrogate an object for some information.

myObject.GetStatus();
myObject.SomeCapabilitySwitch = true;

In thinking about it, when I first started coding in C#, I wrote a lot of code in the Javabeans style illustrated above. But as I gained experience in the language, I began doing more setting of members in the constructor, and using methods that looked more like the above OO style.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • 6
    Why is the "give all arguments as parameters" OO-style? –  Nov 27 '10 at 06:39
  • 7
    While your "OO-style" is fine for 2 or 3 options, I would prefer JavaBean style once you get above that. Having 20 overloaded methods for every possible combination of parameters just looks terrible – TheLQ Nov 27 '10 at 19:38
  • 3
    @TheLQ: C# 4.0 makes this easier by allowing optional and named parameters in constructor and method calls. – Robert Harvey Nov 27 '10 at 22:40
  • 9
    @TheLQ That's what Builder with fluent syntax is for, see e.g. [Guava's MapMaker](http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/MapMaker.html). – maaartinus Aug 06 '11 at 16:35
  • I've recently been looking into chained functions like those used in jQuery for cases where there are more than 5 options. I'm not sure how well it fits into OO programming though... – Ivan Oct 03 '11 at 15:58
  • 8
    @Thorbjørn Ravn Andersen, I'd say "give all arguments as parameters" is better OO-style than "call JavaBean setters" because a setter implies there is an underlying attribute being set, which by definition exposes internal details. Using the connect(..) method in the example makes no such assumption; maybe you set a user and password attributes, maybe you don't. What's important is that you focus on the right OO concept: the "connect" message. – Andres F. Nov 21 '11 at 16:03
  • Of course, if you want to be able to ask the object what the username / password used to connect was, you'd need some way to get them, and then the first style makes a lot more sense since you need a getter anyway, might as well have the setter (or properties in C#). – Andy Jul 15 '15 at 14:59
  • 2
    @Andy I disagree if you have a UI, even a very simple one, a core interface like a Connection, that serves both batch mode and interactive mode use cases, should not be changed to accommodate it. The onus is on the UI to gather the username and password together before calling `Connect`. – Aluan Haddad Oct 17 '17 at 02:27
  • @AluanHaddad Nonsense. The UI **absolutely** influences the business layer. The UI is the visual representation of the use case the user is operating under. Also in C# (and Java I believe), using databinding requires properties (getters/setters). Not using databinding actually leads to writing more and duplicate code (i.e., validation, as objects which are databound can implement [IDataErrorInfo](https://msdn.microsoft.com/en-us/library/system.componentmodel.idataerrorinfo(v=vs.110).aspx) which allows the UI to query the object to find out what the problem is and show to the user. – Andy Oct 17 '17 at 12:35
  • 2
    @Andy I'm suggesting that you could store the these fields in a separate structure, one with Getters and Setters, that is used to connect to the database when both are filled in. That allows the connection to still require both fields before attempting to connect. This data structure could be a simple class or a closure. Another option would be to have the connection return a builder. – Aluan Haddad Oct 17 '17 at 16:43
  • @AluanHaddad Or you can keep it simple and just put the properties on the connection. The connection is useless without a username and password; there's no reason to divorce the state from the behavior that needs that state. – Andy Oct 17 '17 at 21:37
  • So, when you finally come around implementing auto-reconnect functionality you're going to carry `"dukie"` and `"duke"` around as arguments through dozen of state-checking and connection dropping and re-initializing functions just in case that it happens that yes, you need to call `connect` once again because it explicitly needs them as arguments? Instead, you know, setting them once as in your first example? – Oleg V. Volkov Aug 14 '19 at 06:57
  • @Oleg V. Volkov Not having setters/getters for something doesn't mean you don't store information in some way. Instead you can add a `reconnect` method which doesn't need parameters and instead reuses settings from the existing parameters. – Hedede Aug 17 '21 at 05:42
  • For example, in our internal framework uses this approach: a `connect` method which takes either a connection string or host, port, login password. User of the interface doesn't know anything about how this information is stored - it might be stored as separate fields, or as a connection string, or both, or not at all - it might be stored by an underlying library. – Hedede Aug 17 '21 at 05:53
21

When are getters and setters justified?

When the behavior "get" and "set" actually match up to behavior in your model, which is practically never.

Every other use is just a cheat because the behavior of the business domain is not clear.

Edit

That answer might have come across as flippant, so let me expand. The answers above are mostly correct but focus on the programming paradigms of OO design and some what miss the big picture. In my experience this leads people to think that avoiding gettings and setters is some academic rule for OO programming languages (e.g people think replacing getters with properties is grand)

In fact it is a consequence of the design process. You don't have to get into interfaces and encapsulation and patterns, arguing over whether it does or doesn't break these paradigms and what is or isn't good OO programming. The only point that ultimately matters is that if there is nothing in your domain that works like this by putting them in you are not modeling your domain.

The reality is that it is highly unlikely that any system in your domain space has getters and setters. You cannot walk up to the man or woman who is responsible for payroll and simply say "Set this salary to X" or "Get me this salary". Such behavior simply doesn't exist

If you are putting this into your code you are not designing your system to match the model of your domain. Yes that breaks interfaces and encapsulation, but that isn't the point. The point is that you are modelling something that doesn't exist.

More over you are probably missing an important step or process, because there is probably a reason I can't just walk up to pay roll and say set this salary to X.

When people use getters and setters they tend to push the rules for this process into the wrong place. This is moving away from your domain even more. Using the real world example, it is like salary assuming that the random person who walked in has the permission to get these values otherwise he wouldn't be asking for them. Not only is that not how the domain is, it is in fact lying about how the domain is.

Cormac Mulhall
  • 5,032
  • 2
  • 19
  • 19
  • this doesn't seem to offer anything substantial over points made and explained in prior 17 answers – gnat Sep 08 '14 at 10:12
  • 3
    The other answers talk about objects, interfaces and other languages paradigms. Which is fine, but it is not the central issue. Getters and setters are not just bad because they break some coding conventions, but primarily because you hardly ever encounter this behaviour in the actual model you are representing. This point tends to get lost in the discussion about the best coding practices. – Cormac Mulhall Sep 08 '14 at 10:42
  • Just what do you think the interface to payroll is if it isn't `set/get` salary? – Winston Ewert Sep 08 '14 at 17:50
  • The interface to payroll should model the business, ie the interface should reflect the business rules of the company. No company has a payroll department with 'get' or 'set' process, where anyone can walk up and either get someones salary or set someones salary. No payroll department behaves like that so that behaviour should not be reflected in the software model. Build what already exists, cause I'm pretty sure your payroll department has already figured out how to manage access to employee salaries. – Cormac Mulhall Sep 09 '14 at 08:52
  • 1
    On the contrary, many businesses **do** have the equivalent of get and set payroll processes. Granted, those processes are wrapped within authorization layers but there are getters and setters nonetheless. An employee's manager sets the employee's salary; it's not payroll that does that. Likewise, the manager's manager can get the salary information for all of their reporting employees. –  Sep 09 '14 at 13:48
  • 3
    If they are wrapped around authorization layers and restricted to certain external entities they are not getters and setters. I'm not saying don't have any method on the payroll department that changes the salary, but that method should align with the internal processes in place in the company itself. For example most companies set salary based on the employees contract, which is authorized by a manager. If the employee's salary changes a new contract is drawn up and a manager has to sign it. Therefore payroll should expect a contract object and some authorisation object to change pay roll – Cormac Mulhall Sep 09 '14 at 14:17
  • 4
    Or to put it another way, there is quite a difference between set_salary(new_salary, employee_id) and authorized_salary_update(employee_contract, authorising_manager). The process should model the internal business process – Cormac Mulhall Sep 09 '14 at 14:23
15

As a general rule, getters and setters are a bad idea. If a field isn't logically part of the interface and you make it private, that's fine. If it is logically part of the interface and you make it public, that's fine. But if you make it private and then turn around and make it effectively public again by providing a getter and setter, you're back to where you started except your code is now more verbose and obfuscated.

Obviously, there are exceptions. In Java, you might need to use interfaces. The Java standard library has backward compatibility requirements so extreme as to outweigh normal measures of code quality. It's even possible that you may actually be dealing with the legendary but rare case where there's a good chance you may later replace a stored field with on the fly calculation without otherwise breaking the interface. But these are exceptions. Getters and setters are an anti-pattern that needs special justification.

rwallace
  • 1,198
  • 11
  • 19
  • 7
    A getter and setter mean that the attribute, not the field, is part of the interface. Suppose getBirthDate() and SetBirthDate() take "yyyy/mm/dd" but the field stored is the number of days since 01/01/1000. You can change that to 01/01/0001 and the getter and setter will keep the interface the same. Especially because 'public' means publically trashable, variables should never be public; always use a setter to validate the incoming value, update any related fields, convert as needed, etc. Try to use a getter in case the internal storage changes. – Andy Canfield Oct 04 '11 at 07:35
  • @AndyCanfield that's a bit strong to say public means publicly trashable..That's only so if u program it badly. If you have a setter and the wrong value is sent to it then u could throw an exception which u could call trashing the program but it's quitting with an errorAlso if the user of the object can give a variable a value and cud give it the wrong value then u can bear that in mind and test it.u may say "ah but I only have to do 1 test if I use a setter",but maybe ur own code gives the variable a bad value..so the setter might not reduce your tests.n with tests,ur prog isn't "trashed" – barlop Feb 01 '15 at 05:31
4

whether field is accesible directly or via method is not realy important.

Class invariants (usefull ones) is important. And to preserve them, we sometimes need to not be able to change something from outside. Eg. if we have class Square with separete width and height, changing one of them makes it become something else than square. So we need method changeSide If it was Rectangle, we could have setters/public field. But setter than would test whether its greater than zero would be better.

And in concrete languages (eg. java) are reasons why we need those methods (interfaces). And another reason for method is compatibility (source and binary). So its easier to add them then think whether public field would suffice.

btw. I like to use simple immutable value holding classes with public final fields.

user470365
  • 1,229
  • 6
  • 8
  • This is pretty much the only thing that should be avoided. Going from field to property/getter/setter is a breaking change in most languages. – MrDosu Sep 16 '14 at 11:13
2

You may want to change your internals to whatever while keeping the interfaces the same. If your interfaces don't vary, them you code won't break. You still can change your internals as you wish.

George Silva
  • 371
  • 1
  • 9
  • 1
    I'm surprised this answer is so far down. Getters and setters allow you to do more in the future (e.g. fire an event, do more input validation, do internal bookkeeping) without breaking your existing API. Even with non-public code, the fewer APIs you have to change, the fewer dependencies to update, and the fewer bugs introduced making those updates. – AmadeusDrZaius Apr 27 '16 at 06:00
1

Firstly there are broadly two types of objects which i will comment on, value and service types.

Service types should never have setters, whatever dependencies they require should not be gettable. THe best way to pass dependencies is via a constructor or factory that way all instances are fully formed from the beginning, plain and simple.

Value types should also be immutable, on the oher hand there are times when this is not practical such as an ORM, or some other mapping such as from a widget to an object. All other value types that get passed around the system from one layer or part to another should be immutable and should not have setters.

mP01
  • 291
  • 1
  • 8
  • I'd suggest a third type: a mutable container, whose purpose is to hold one or more values; in many cases, a container should not be expected to have much in the way of logic or validation. Code which needs a method to compute six positive integers may pass a container for six integers to the method which will store the results therein. Responsibility for ensuring the numbers are positive should generally lie with either the caller or the called method, not with the container. – supercat Jan 13 '16 at 22:37
1

If using getters and setters feels complicated, the problem might be the language, not the concept itself.

Here's the code from the second example written in Ruby:

class Fridge
  attr_accessor :cheese
end

def go_shopping fridge
  fridge.cheese += 5
end

Notice it looks a lot like the first example in Java? When getters and setters are treated as first class citizens, they're not a chore to use, and the added flexibility can sometimes be a real boon - for example, we could decide to return a default value for cheese on a new fridge:

class Fridge
  attr_accessor :cheese

  def cheese
    @cheese || 0
  end
end

Of course there will be many variables that shouldn't be exposed publicly at all. Needlessly exposing internal variables will make your code worse, but you can hardly blame that on getters and setters.

Tobias Cohen
  • 131
  • 4
  • That is beautifully stated. Builder functions were added because we want to create immutable objects while gradually building up the recipe: maybe if you add artificial sweetener, you don't need to add sugar. Using named parameters, and even with overloading, it is very hard building one method doing all. And then of course java doesn't have named parameters, hence one more reason people are using the Builder pattern. – YoYo Jan 13 '16 at 00:38
0

Consider a Size class which encapsulates width and height. I can eliminate setters by using the constructor but how does that help me draw a rectangle with Size? Width and height are not internal data to the class; they're shared data that must be available to the consumers of Size.

Objects consist of behaviors and state - or attributes. If there is no exposed state then only behaviors are public.

Without state, how would you sort a collection of objects? How would you search for a specific instance of an object? If you only use constructors, what happens when your object has a long list of attributes?

No method parameter should ever be consumed without validation. Therefore it is laziness to write:

setMyField(int myField){
    this.myField = myField;
}

If you do write it that way then you have at least prepared for using the setter for validation; it's better than a public field - but just barely. But at least you have a consistent public interface that you can come back and put in validation rules without breaking the code of your customers.

Getters, setters, properties, mutators, call them what you will, but they're necessary.

Jalayn
  • 9,789
  • 4
  • 39
  • 58
Dale
  • 1
  • *But at least you have a consistent public interface that you can come back and put in validation rules without breaking the code of your customers.* That's not true. Adding validation rules further down the road could very well "break the code of your customers". Take an `int` instance variable, for example, and imagine that you decide to add a validation rule to only accepts nonnegative values. The problem is that your customer's code may already rely on the possibility to set it to a negative value... – jub0bs Nov 01 '15 at 14:19
0

My approach is this -

When I expect to diddle with the data later on, a getter/setter is justified. Also, if change is happening, I often push the data into a getter/setter.

If it's a POD structure, I leave the slots available.

On a more abstract level, the question is "who manages the data", and that depends on the project.

Paul Nathan
  • 8,560
  • 1
  • 33
  • 41
0

In Swift, there are variables (class, instance, and static variables) which are quite the same as properties. And for every variable, you can add a getter and a setter if you wish to do so, plus code to be called before the setter is called (with a parameter "newValue") and code to be called after the setter is called (with a parameter "newValue).

The variable itself can be private or public (or fileprivate, or internal, or open; these are Swift specific), and the setter can be private.

If it's private it doesn't expose anything (and fileprivate only exposes within one source file). If you have a private setter, it can't be modified without control so you are always safe. And if you have a getter, then it doesn't expose any internal state. It only exposes what the interface says it exposes.

Perfectly object oriented. What you see may be the internal state, maybe it's not. I might have four temperate classes Kelvin, Celsius, Fahrenheit and Reamur which all store temperature in degree Kelvin internally - but only one exposes this directly as a property. And you don't know which one (since the could all four store the temperature in Celsius), and it doesn't matter. Only the interface matters.

The only difference between a variable and a function is mostly that functions have () appended :-) And you don't have a "get" or "set" prefix. And variables should be used for things that are reasonably fast.

BTW. Swift allows fridge.cheese += 5 (no semicolon), calling a "getter" and a "setter".

gnasher729
  • 42,090
  • 4
  • 59
  • 119
-1

If getters and setters violate encapsulation and true OO, then I'm seriously in trouble.

I always felt an object represents whatever best comes to mind that you need it to do.

I have just finished writing a program that generates Mazes in Java, and I have class that represents "Maze Squares". I have data in this class that represents coordinates, walls and booleans etc.

I have to have some way to change/manipulate/access this data! What do I do without getters and setters? Java doesn't use properties and setting all my data that is local to this class to public is DEFINITELY a violation of encapsulation and OO.

SusanW
  • 1,035
  • 10
  • 14
Bryan Harrington
  • 2,502
  • 1
  • 19
  • 22
  • 7
    Here is the question: If you made all those fields public, and stopped using the getters and setters how would your code be different? – Winston Ewert Nov 27 '10 at 15:10
  • In theory, its not. Why even make a class at that point? Same argument could be made with anything. But the post below mine seems to have said it more elegantly. (Getters and setters are a way to safely hand a value to an object, or retrieve a value from that object.) The post goes on.. – Bryan Harrington Nov 27 '10 at 15:14
  • 3
    I'd point out: that poster eventually agreed with me and posted another answer to that effect. Essentially, using getters and setters is the same as manipulating the data directly. You don't really gain OOness by doing that. In order to be OO you ought to provide a higher level interface to the data. – Winston Ewert Nov 27 '10 at 15:29
  • 5
    I think the best way of describing it would be to say that you should design your interfaces from the outside in, not the inside out. The interface your object provides should be dictated by how the object is used not how it is implemented. So don't write getters and allow external object to interpret the data. Find out what question they need answered, and write a method that answers that question. Don't allow external objects to modify state by a setter, find out what kind of manipulations they need to perform and write methods that do that. – Winston Ewert Nov 27 '10 at 15:31
  • 2
    In some cases, Getters and Setters are the best method. Sometimes they are the best interface you can provide. However, in many cases they are not. In many cases, you are just leaking implementation details into other classes. – Winston Ewert Nov 27 '10 at 15:32
  • You can manipulate the data inside the object that contains this data. In this way you may not need direct access to the data. If your code is public I can perhaps suggest ways to do this. – Jon Acker Jul 12 '22 at 10:12