Getters and setters: evil or necessary evil?

I’ve been reading a lot about getters and setters over the last few years, including Alan Holub’s infamous article “Getters and setters are evil“, and Martin Fowler’s article “GetterEradicator.” Although I do still feel like getters and setters are to be avoided most of the time, it’s hard to tell where to use them and where you shouldn’t.

I’ve been working on the website of PFZ.nl, the largest PHP community in the Netherlands, together with about eight other programmers I can’t help but respect. While writing the code for this website, I started to notice that each and every class in the system had accessors for most, if not all, protected fields. I’ve started a discussion with my fellow developers, and this is what I’ve argued.

First, I wrote an article on it, which was rather ill-received by some. This is understandable, as the presence of accessors is deeply rooted in OO PHP code, although this isn’t limited to one specific language. Besides, my point of view sounded rather puristic in my first article. Before I want to discuss why accessors should be handled with care, I’d like to go back half a century, to the introduction of OO.

Back in the day, some great minds thought up the concept of OO to make sure software would be easier to change, which means it’s easier to maintain. To accomplish that, they thought up the concept of an Object: a small, focused unit of code that is only ever responsible of one thing. One of the key concepts of OO was that objects should hide their implementation, to let their collaborators send them messages that they could handle for themselves. This concept became known under the term “Encapsulation”, a reinforcement of the guideline “Tell, don’t ask.”

Wikipedia states that the term encapsulation is used to refer to one of two notions: either to restrict access to an objects’ internals, or a language construct that facilitates the bundling of data, and methods operating on said data (which I like to call behaviour). Since the arrival of (decent) OO functionality in PHP, I have seen a lot of accessors which don’t adhere to the above concept: they actually willingly expose implementation, instead of hiding it.

This is not necessarily a bad thing, and sometimes, this even makes sense. The problem doesn’t actually lie with exposing the implementation and the data, but with the collaborator that *directly* uses that data. The number one example of misusing exposed data would be a bank account object: you can either opt for having setBalance( $balance ) and getBalance( ) methods, but common sense would dictate different methods: withdraw, deposit, and transfer. The number one reason for these methods is that the collaborator knows *nothing* about what a balance is, nor should it have to.

Translating this example to (PHP) code, the first option with accessors would probably result into the following class and collaborator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class BankAccount {
	protected $balance;
	public function setBalance( $balance ) {
		$this->balance = $balance;
		return $this;
	}
 
	public function getBalance( ) {
		return $this->balance;
	}
}
 
class Transaction {
	public function transfer( $amount, BankAccount $from, BackAccount $to ) {
		if( ( $from->getBalance( ) - $amount ) < 0 ) {
			throw new InsuffientFunds( );
		}
		$to->setBalance( $to->getBalance( ) + $amount );
		$from->setBalance( $from->getBalance( ) - $amount );
		return true;
	}
}

Now, although this code is easy to write, there might just as well not be a BankAccount object, as it actually doesn’t *do* anything. It’s devoid of behaviour. This means that it’s a useless object which might just as well be nuked. Refactoring to the second option (withdraw, transfer, deposit), the resulting code might be something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class BankAccount {
	protected $balance;
	public function tranfer( $amount, BankAccount $to ) {
		$this->withdraw( $amount );
		$to->deposit( $amount );
	}
 
	public function withdraw( $amount ) {
		if( ( $this->balance - $amount ) < 0 ) {
			throw new InsufficientFunds( );
		}
		$this->balance -= $amount;
		return;
	}
 
	public function deposit( $amount ) {
		$this->balance += $amount;
		return;
	}
}
 
class Transaction {
	public function transfer( $amount, BankAccount $to, BankAccount $from ) {
		return $from->transfer( $amount, $to );
	}
}

Now, this code (in my opinion) is just as easy to read and write, but there’s a very large benefits using the second approach: the ability to change. Imagine, for example, that there’s a “premium” bank account that allows to go in debt to, say, a thousand euros. You’ll have to change both examples in this case, but you’ll see that the second will accommodate this change much easier. Let’s refactor both examples, starting with the one that uses accessors:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
class BankAccount {
    protected $balance;
    protected $overdraw = 0;
 
    public function __construct( $balance, $overdraw = 0 ) {
        $this->balance = $balance;
        $this->overdraw = $overdraw;
    }
 
    public function setBalance( $balance ) {
        $this->balance = $balance;
        return $this;
    }
 
    public function getBalance( ) {
        return $this->balance;
    }
 
    public function getOverdraw( ) {
        return $this->overdraw;
    }
}
 
class Transaction {
    public function transfer( $amount, BankAccount $from, BackAccount $to ) {
        if( ( $from->getBalance( ) + $from->getOverdraw( ) - $amount ) < 0 ) {
            throw new InsuffientFunds( );
        }
        $to->setBalance( $to->getBalance( ) + $amount );
        $from->setBalance( $from->getBalance( ) - $amount );
        return true;
    }
}

Although this works, it’s far from elegant. If you have more than one collaborator for the bank account object, and you usually do, you’ll have to duplicate that logic to all other collaborators. If requirements change, you’ll have to change the logic on each place you’re calculating the balance. There are more issues with the code, but I’ll get to that later. Now, to refactor the well encapsulated version of the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
class BankAccount {
    protected $balance;
    protected $overdraw = 0;
 
    public function tranfer( $amount, BankAccount $to ) {
        $this->withdraw( $amount );
        $to->deposit( $amount );
    }
 
    public function withdraw( $amount ) {
        if( ( $this->balance + $this->overdraw - $amount ) < 0 ) {
            throw new InsufficientFunds( );
        }
        $this->balance -= $amount;
        return;
    }
 
    public function deposit( $amount ) {
        $this->balance += $amount;
        return;
    }
}
 
class PremiumBankAccount extends BankAccount {
    protected $overdraw = 1000;
}
 
class Transaction {
    public function transfer( $amount, BankAccount $to, BankAccount $from ) {
        return $from->transfer( $amount, $to );
    }
}

Alright, the introduction of the new class PremiumBankAccount could have been done with the setters and getters too, but still, the change had just one line. Better yet: the change only affected the BankAccount class itself, and the rest of the application is still blissfully unaware of any change, although the functionality has been radically changed. The collaborator doesn’t know the bank account even can overdraw, nor should it have to.

If you’re still not convinced the second example is better, I’ll play devils advocate and I’ll ask you to refactor both examples to incorporate functionality so that a bank account can have a currency, say EUR and USD, and you should be able to transfer an arbitrary amount of dollars to a bank account based on EUR. You’ll see how much your Transfer class will have to do, when you’re using only accessors.

Alright, I think I’ve made my point by now: the second example is much better, and indeed, it’s OO like OO was meant to be. Now, obviously, you wouldn’t do it like I did it in the first example, right? You’d *maybe* write the accessors, but you’d put the transfer logic into the bank account itself, right? Good for you, but most classes I see out there today actually lean toward the first example, and this yields my curiosity in finding out: why?

Just open an OO library written in PHP, and grep for “function set”, and you’ll be shocked. Again, the problem doesn’t lie with the accessor per se, but you should check the collaborators, and I can guarantee you that the collaborators are doing calculations and making decisions which should belong in the object itself. By exposing the data, you’re making this possible.

If you work with others you can simply expect people to change your objects’ behaviour instead of using the accessors you wrote, or you can provide well named methods that encapsulate the data, so your coworkers know how to use your class.

So, why do we use so much setters and getters if there is seemingly no need to do so? Well, first of all, I’d like to go back a decade, when I was still in school and getting lessons on programming in Java. Indeed, my books were full of getters and setters, so I just assumed this was the way things work. How could I have known better? The people that wrote the books are notably smarter than I am, so they must be right. Right? Well, not so much.

People starting to learn OO are reading books, tutorials and example code which are littered with accessors. It just makes good sense to copy that pattern onto your own code. If, like me, you were used to writing procedural code, you’ll even feel right at home. You still manipulate the variables, only now they’re in some sort of namespaced array called an object. Awesome. I hereby bid people that write introductory tutorials to stop using accessors “because they can”, and instead only write them “because they have to”.

So, “learning it the wrong way” is a big reason, but there’s another one, and that is layering. Layering your application is supposed to make your code more maintainable, more extendable, more reusable, and more of that. In PHP, there is not a single framework that doesn’t claim to “be MVC”, and that is another reason for the presence of accessors everywhere.

If you split up responsibilities into “business logic” (such as transferring an amount to another bank account), and the logic for displaying stuff (such as, when the accounts’ balance is negative, display the balance in red), you’re supposed to be able to change one layer without changing the other. Implementing the separation between those responsibilities will make it easier to display one object in multiple ways.

For example, say I want to display the bank accounts in HTML. I’ve got a few options, one of them being rendering the HTML inside the object itself. Once you start down that road though, your BankAccount class will grow to extreme proportions, as you might want to display the information in HTML, XML, JSON, etc., etc.

Another option is to leave the displaying of the bank account to a template. This template will fetch the accounts’ balance and if < 0, display the balance in red for HTML. Indeed, this is the most widely used technique and, in and on itself, not a bad one to start with. It does have a requirement though: each part of data that you want to display will have to be available to the View layer. As PHP doesn’t know “Friend” classes like C++, and there’s no ability to read protected variables from the same “package” like Java, you’ll have to make the access public. This means that you’ll have to write a public getter for each value you want to display!

On the other side of the object, there’s storage. Generally, objects from the model layer will have to be saved somehow, and that yields the exact same issue: how does the object that saves the values (say, a DataMapper) get the values from the target object? In the exact reverse, how does a DataMapper build the object without being able to set values? You could use the constructor for this, but that might mean you get a constructor with 10+ parameters, which is not the most clean solution ever.

All in all, I don’t think accessors are evil per se, but you should only ever use the accessors in cross-layer situations. Don’t use accessors to build functionality, but only because you need the value to display and/or save.

Category: Object Oriented, programming, Theory, Uncategorized 25 comments »

25 Responses to “Getters and setters: evil or necessary evil?”

  1. Mark Kazemier

    Nice article. I completely agree with your argumentation about getters and setters. Most of the time they are not needed.

    Furthermore, in the MVC pattern getters are also not always necessary. You can also create a pattern where the model class has a render or display method which takes a view object. This method then calls a new method om the view and inserts only the data in that method that you want to share. In this way your data in the model is still encapsulated and you force the user of the class to use the right patterns.

  2. Taco

    Great article, I agree on the sentiment of not using getters and setters wherever possible. However, in your average website it’s hard to resist the temptation, especially (as you describe) cross-layer. I was kinda hoping you would offer a solution for this in the end.

    I personally try per case to avoid opening up the object, most of the time by inverting the control. In a view layer you could call a specific render-method of the model object and even at the db-storage side you could let the other model bind your params without opening it. Ideally I think you should factor these functionalities to new object, although it feels over-the-top most of the time.

    I keep hoping for some ideal solution to pop up, but somehow, I guess there’s no end-to-all-problems fix :)

  3. Jaap Verloop

    I guess you’re right on this but sometimes accessors could be helpful.
    Some projects requires a combination of multiple frameworks, in this case they could be useful to write adapters to glue the different frameworks together.

    Great article, very interesting stuff!

  4. Tweets die vermelden Getters and setters: evil or necessary evil? — Berry Langerak -- Topsy.com

    [...] Dit blogartikel was vermeld op Twitter door Łukasz Chojnowski, Berry Langerak. Berry Langerak heeft gezegd: New blog post: Getters and setters: evil or necessary evil? http://bit.ly/i1HKq1 [...]

  5. mario

    The prevalence of getters and setters in PHP is also rooted in a tendency to overuse access modifiers. PHP didn’t have them for a long time, the object model was perceived (rightly) as inadequate, and it is overcompensated for (by mimicking Java).

    While “encapsulation” is the correct explanation for using access modifiers, the usual explanations fall short. It’s unknown to PHP coders, but restricting the attribute access at the source code level is just a secondary feature of those modifiers. Originally they were intended for compiled code, where limiting symbol exports to either local objects or derived objects would save ABI incompatibilities and recompilation. It’s a use reason that is overlooked in scripting languages, because it’s not applicable and hence the hypothetical security by-product is usually overstressed.

    But obviously your analasis is true. PHP code is often simply structured too low-level. But I’m not sure if the usage domain might have contributed to that, or if it’s really just the prevalence of cursory tutorials.

  6. Thomas Schäfer
    class InsufficientFunds extends Exception{}
     
    interface Account{}
    class BankAccount implements Account
    {
      protected $balance = 0;
      protected $overdraw = 0;
     
      public function transfer( $amount, BankAccount $to ) {
        $this->withdraw( $amount );
        $to->deposit( $amount );
        return $this;
      }
     
      public function withdraw( $amount ) {
        if( ( $this->balance + $this->overdraw - $amount ) balance -= $amount;
        return;
      }
     
      public function deposit( $amount ) {
        $this->balance += $amount;
        return;
      }
     
      public function __get($name)
      {
        $o = debug_backtrace(false);
        array_shift($o);
        $c = array_shift($o);
        if(is_array($c) and array_key_exists("class", $c) and $c["class"]==='AccountReader')
          return $this->{$name};
        else
          throw new Exception("May only be called by a AccountReader");
      }
     
    }
     
    class PremiumBankAccount extends BankAccount {
      protected $balance = 500;
      protected $overdraw = 1000;
    }
     
    class SecondBankAccount extends BankAccount {
      protected $balance = 500;
      protected $overdraw = 1000;
    }
     
    class Transaction {
      public function transfer( $amount, BankAccount $to, BankAccount $from ) {
        return $from->transfer( $amount, $to );
      }
    }
    class AccountReader
    {
      private $account;
      public function __construct(Account $account){
        $this->account = $account;
      }
      public function read()
      {
        $r = new ReflectionObject($this->account);
        $p = $r->getProperties();
        foreach($p as $key => $val)
        {
          $p = new ReflectionProperty($this->account, $val->name);
          if($p->isProtected())
          {
            echo $this->account->{$val->name};
          }
        }
      }  
    }
     
    $t = new Transaction();
    $a = new AccountReader($t->transfer(120, new SecondBankAccount(), new PremiumBankAccount));
    $a->read();
  7. Laurent Pireyn

    Accessors are methods, and as such they are actors in the OO paradigm.

    An accessor allows neat tricks such as lazy initialization (for getters at least), synchronization, logging, and much more. Some common patterns (e.g. wrappers, decorators) rely on polymorphism, and work only if you access the state of an object through its methods.

    In Java, some frameworks and libraries work much better with accessors (e.g. ORM such as Hibernate or JPA), precisely because they rely on method overrides instead of direct field access.

    Granted, I’m a Java programmer, so my comment is probably not as pertinent for other, less OO languages such as PHP.

  8. Nicolas

    I know that in java we use accessor not because they are good or bring value but because it is an old standard.

    So basically, when what you need is basically a C struct, instead of using public fields, you use private one and add getters/setters.

    People argue that one time out of 10 thousand you may need to add behaviour and that get/set are great then. Most people do it because they are used to, or it is required by their framework.

    Through adding behaviour in object or outside object is a matter of taste/philosophy.

    OOP state that you should stick data with code whereas functionnal programming state the other.

    And even, the best OOP gurus admit that procedural code is sometime better and encapsulation is overlooked.

  9. Berry

    Hi Laurent,

    > An accessor allows neat tricks such as lazy initialization (for getters at
    > least), synchronization, logging, and much more. Some common
    > patterns (e.g. wrappers, decorators) rely on polymorphism, and work
    > only if you access the state of an object through its methods.

    I wasn’t saying that accessors don’t have their place in an Object Oriented application, I’m just saying the PHP community (at least?) tends to write them before considering whether or not it is even used. I’m focussing more on an accessor that simply sets or retrieves the (scalar) value of a property, without actually *doing* something to the value, only to store that behaviour in a collaborator and duplicating that behaviour in case there are multiple collaborators.

    If you’re using Java and I’m not mistaken, you should be able to access protected methods from within the same package, so I don’t see any need to expose the accessor to the “public”, as it were. PHP does not have that luxury. :(

    > In Java, some frameworks and libraries work much better with
    > accessors (e.g. ORM such as Hibernate or JPA), precisely because they
    > rely on method overrides instead of direct field access.

    Yep, which makes a whole lot of sense. I’ve created a project on Github (ObjectMutator, PHP only) which will try to set values on an object, either by calling an accessor, or setting the value directly if no setters was provided for it. In my experience, nine out of ten times, accessors are “stupid” in that they don’t do anything before setting or returning the value.

    > Granted, I’m a Java programmer, so my comment is probably not as
    > pertinent for other, less OO languages such as PHP.

    Probably. I work with Java too from time to time, but I still don’t have a lot of setters and getters: I generally simply don’t need them. It’s a matter of putting the behaviour in the right object.

  10. Berry

    Hi Nicolas,

    > I know that in java we use accessor not because they are good or bring
    > value but because it is an old standard.

    That’s what I was arguing. It’s (becoming?) a standard in PHP just as well, and I just don’t get the added benefit of writing or generating accessors that shouldn’t be there in the first place. Funny enough, our standard seems to stern from the Java standard.

    > People argue that one time out of 10 thousand you may need to add
    > behaviour and that get/set are great then. Most people do it because
    > they are used to, or it is required by their framework.

    Behaviour isn’t just a buzzword; to me, it’s pretty much the foundation of object oriented programming. Without adding any type of behaviour to any type of object, you’re building functions which are essentially procedural functions that use some sort of arrays (fyi, we call everything an array in PHP). In that case, you might as well nuke the whole idea of OO and start writing procedural code that actually uses arrays? Less costly, easier to read, and less code to be written.

    > Through adding behaviour in object or outside object is a matter of
    > taste/philosophy. OOP state that you should stick data with code
    > whereas functionnal programming state the other.

    You might be right, it might well be a matter of taste. But to me, putting behaviour in an object and telling that object to do something is infinitely better than asking the object for information only to implement that same behaviour.

  11. Wil Moore III

    >> nine out of ten times, accessors are “stupid” in that they don’t do
    >> anything before setting or returning the value.

    I agree with this statement; however, it leaves out some important caveats.

    1 – An accessor method, even if it provides no other domain logic beyond returning it’s underlying field data, is a better API design as it protects from potentially breaking the API when domain logic must be factored in. This is a huge part of iterative development.

    2 – See #1 and ignore it if you are primarily working alone and not in a team — also, ignore #1 if you are the only one to ever consume this API.

    3 – Just because you don’t have a need for accessors at the outset doesn’t mean you won’t need them later.

    I also notice (not just here but in a lot of PHP debate articles) a lot of comparisons with Java; however, Java is not the only language to utilize these concepts we debate.

    For instance, Ruby *BAKES* into the language the very thing we are debating here.

    attr_accessor :balance

    The above generates an accessor and mutator method. The only way to access an instance variable outside of the object is with an accessor method.

    I guess my argument here is that we stop bashing Java and pick on a language that can actually defend itself on a more level playing field. I would assume that bashing session wouldn’t last very long :)

  12. Stephen Young

    I definitely think setters are evil. I don’t usually write getters for the sake of writing getters, but I know one scenario where I end up writing lots of getters: Interfaces!

    If I need to ensure that a class implements a certain parameter, I’ll make sure the interface has a getter for that parameter.

  13. Nicolas

    The question finally is what you are really doing in your software.

    Many software do that :

    - Listen for HTTP request with HTTP parameters
    - Embed theses parameters into a behaviour less object.
    - Send this object to the business layer that do nearly nothing but forward it to the access layer.
    - The access layer use it to generate a request to the database.
    - The access layer put the response to a list of behaviour less objects.
    - The business layer get the response from access and transform it to bring it back to the UI
    - The UI show it on the screen.

    If you really try to understand this pipeline, you see that this design :
    - Allow easy changes : UI / Access can be changed with minimal impacts
    - Allow good encapsulation : UI can corrupt Access/Business data. And Access can’t corrupt Business/UI data too.
    - That this not OOP at all. This is a plain procedural pipeline. This is simply a very good pratice. Not everything fit in an OOP way. Basically in this design, we might use object and interfaces, but we don’t do OOP other that for technical reason and because we do program with an OO language.

    Then there is no need at all to use getter/setters. They serve nothing. Public fields are more consise. Using a map can even be a better choice if you don’t mind having type/name information at runtime only. Then your business layer and access layer is reduced to nearly nothing and use 99% the same generic code. (Think about ActiveRecord).

    The thing is that theses sort of applications are in reality data driven. The more objects, the more OOP you try to bring in (using ORM with complex class hierachy for exemple), the more complex your project become and the more problems you have. Introducing OOP in this sort of application is just introducing what we call an impedance mismatch.

    Why they are data driven ? Because basically all you do is CRUD operations. There is nearly no business. Just a UI and a database. That’s why plain old PHP is so good for that sort of applications/website. You don’t loose time on useless OO design. You design your datamodel instead.

    All data intensive applications have the same sort of concern. 3D Video games for exemple. At first using objects everywhere seems good. But then your data are not ordered and aligned in memory. You have lot of cache miss, because you loose spacial proximity. Your graphic card (that is a giant pipeline) rely on spacial proximity and have cache everywhere. What your GPU want is a big array of data. But if you use too much objects, too much new everywhere instead of big array, your performance will be abyssal hurting the hardware.

    A good architechture is not something that we choose because we like it, even because it is beautifull, but because it is efficiant and simple.

    You should think OO when you really need the concepts. When coupling data and code make sence and really help the modelisation of your domain. When polymorphism bring really something interresting to the table.

    There is a hint of the limitations of OOP. A hint that nearly everybody have seen at school. Of course the teacher didn’t speak about them. You guess what is it ? Well it is the examples you are given to understand OOP.

    When you are lucky, they give you good exemple like an UI framework (where any specialised widget appear to be a standard widget with a specialized behavior).

    But how many time your are given silly exemple ? Like animal that make smell ? Vehicules with it subhierarchy (Car / Plane…) that just have a method that print the noise they make ? Or shape that draw themselves ?

    Do you understand what is the real problem about theses examples ? You’ll never have to modelize something like that in most softwares. The best OOP example you are given are simply useless theoretical example that nobody care about in reality.

    Well you can have the exemple of the library. And you will modelize it. Just for the fun… Try it to modelize it with a data driven approach (3NF, relationnal databases and all) and try to not espacialy use objects concepts. You’ll see that your design with be perfectly right and efficiant.

    In most modern project we don’t use OOP to modelize something real. No. Oh we do use pattern. An abstract factory, a singleton, things like that. We use inheritence to reuse code more than to really modelize a class hierarchy that as sence for the domain.

    We use OOP most of the time for purely technical concerns. It is not especially better, it is just that well we have OO languages and that we use what our languages can do.

    An interface is basically a glorified header file in C. (And an interface has nothing to do with OO, it has no behaviour). Many objects we use have no behaviour, but just data containers. The pattern we use are here for technical concern. How to be able to mock this service for testing ? How to be able to replace this implementation with another one ? How to ensure that we have only one instance of this thing at runtime ?

    OOP is hype. OOP is a buzzword. It is usefull, but overlooked.

  14. Berry

    Hi Wil,

    > 1 – An accessor method, even if it provides no other domain logic beyond
    > returning it’s underlying field data, is a better API design as it protects
    > from potentially breaking the API when domain logic must be factored in.
    > This is a huge part of iterative development.

    I fail to see how adding an accessor only when the need becomes clear will break an existing API. Also, in my book, iterative development also means don’t build today what you may need tomorrow. If you plan ahead for a possible change in the future, you’re planning too much. TDD actually dictates that you should do the simplest thing that works, and refactor afterwards. I’ve done TDD on a few projects, and there were no (unnecessary) accessors to be found. YAGNI++

    Apart from that, I still stand by the thought that normal methods still facilitate changes much better than having a bunch of accessors. Part of the success from iterative development is that it facilitates change. OO facilitates change by containing the behaviour in one single unit. All in all, I’m not sure I agree with you.

    > 2 – See #1 and ignore it if you are primarily working alone and not in a
    > team — also, ignore #1 if you are the only one to ever consume this API.

    Breaking your own code would be just as bad as breaking others’ code though right? The only benefit is that you only affect your own code, and you will know what you’ve changed. That’s a plus.

    > 3 – Just because you don’t have a need for accessors at the outset doesn’t
    > mean you won’t need them later.

    And vice-versa: just because you have a parameters, doesn’t mean you’ll ever need an accessor for it — if you keep behaviour in the Unit itself, that is. Mind you, I’m still not trying to bash accessors in general: I’m talking about collaborators that take over behaviour that belongs to another object.

    > I also notice (not just here but in a lot of PHP debate articles) a lot
    > of comparisons with Java; however, Java is not the only language to utilize
    > these concepts we debate.

    I’m not comparing to PHP to Java a lot in the article though am I? I merely stated I was introduced to accessors in my Java classes, and that PHP seems to have borrowed the whole “we need accessors for everything”-attitude from Java.

    > For instance, Ruby *BAKES* into the language the very thing we are
    > debating here.

    If that’s what you think we’re debating, I’m afraid we’re not on the same subject. My point is that you should wonder if code actually belongs in class A, if all it does is use data from class B, where class B consists solely of accessors. And yes, accessors create that possibility, which means that when you write them, you’ll want to wonder if you aren’t “Doing it wrong” ;) It may sound rediculous to you, but in PHP, it seems to be a common phenomenon.

    > I guess my argument here is that we stop bashing Java and pick on a
    > language that can actually defend itself on a more level playing field.
    > I would assume that bashing session wouldn’t last very long

    I actually *like* Java, so I don’t bash it at all. All the mentions on Java in the comments is because the commenters are Java developers.

  15. Alex Prider

    Berry. If you fail to see how adding an accessor only when the need becomes clear will break an existing API then imagine a situation where your team uses a public varible 1000+ times and then you need to alter the value they receive based on some dynamic environment. You will have to update the code in 1000+ different places (switching to method calls).

    The example is simple because I just wanted to say – nobody(!) ever uses accessor methods to move business logic outside an object but to achieve different kinds of polymorphism or make it achievable.

    I hope you really meant you are against public properties and not against accessor methods. Otherwise the point is senseless, a usual programmer does not do what you have explained (and we don’t count newbies).

  16. Berry

    Hi Alex,

    > If you fail to see how adding an accessor only when the need becomes
    > clear will break an existing API then imagine a situation where your
    > team uses a public varible 1000+ times and then you need to alter the
    > value they receive based on some dynamic environment.

    Agreed: if your team uses a public variable 1000+ times, and they use it and apply logic to it, the brown substance has hit the fan.

    > The example is simple because I just wanted to say – nobody(!) ever
    > uses accessor methods to move business logic outside an object but
    > to achieve different kinds of polymorphism or make it achievable.

    I hate to break it to you, but you’re contradicting yourself somewhat. You’re telling me that nobody(!) will ever use accessor methods to move business logic outside of an object, but you’re also telling me your team uses a public parameter to move business logic outside of an object?

    > I hope you really meant you are against public properties and not
    > against accessor methods. Otherwise the point is senseless, a usual
    > programmer does not do what you have explained (and we don’t count
    > newbies).

    Perhaps not your colleagues, but I see it happening a lot in PHP projects. I’ll try to find some real life examples for you to enjoy.

  17. Compilado de enlaces « Programación – por droope

    [...] Excelente artículo sobre si usar o no usar getters y setters para nuestros objetos, y sobre cuando es práctico hacerlo. [...]

  18. Phill Pafford

    Hi Berry,

    Great post! Any chance you are doing more on this topic? or should I say style of development?

  19. Berry

    Thanks! Yeah, I’ll try to write up on some stuff this weekend, so keep your eye on the blog! ;)

  20. The great (PHP) getter/setter debate | Gargoyle

    [...] on this front that Berry Langerak puts forward a good case, and where I want to add my two cents worth. Berry attempts to stress that [...]

  21. OZ

    Getters and Setters aren’t evil. Idea of Encapsulation is not just hide fields, but hide, how class works. Getters and setters can be declared in interface, so you can replace one abject by another – and it is what for encapsulation was invented!

    `withdraw` and `deposit` it’s setters. All this code can be successfully done in `setBalance` method, almost nothing will be changed. All these checks, comparison – it’s usual work of setters.

    Why public fields are evil? Because object can’t control their changing and because they can’t be declared in interfaces. Getters and setters can do it, so it’s perfect tool of OOP.

    Accessors can be written silly, of course, but it doesn’t mean that they are evil. Any method in the class can be written silly.

  22. Theodore R. Smith

    Inside your view, do this:

    balance;
    }
    }

    Then only in your controller you would request the ViewableBankAccount instead of BankAccount, but only when you need the data.

    If you’re not using dependency injection, this will be a pain, but your app wouldn’t be very well designed any way, if that’s the case.

  23. jay

    Wonderfully explained..had a chance to see many great programmers perspectives also.

  24. Mitch

    Your examples, in my opinion, are better left to a controller than to the objects themselves. An account controller should withdraw from an Account object’s balance by using setBalance and getBalance on the Account object and getAmount on the Transaction object. For example…

    $account->setBalance($account->getBalance() – $transaction->getAmount());

    In this case, it’s fruitless to have withdraw, deposit, and transfer methods on the objects. Obviously, this is a matter of your particular application design preference. Fat objects v. fat controllers.

  25. php automated setter and getter - PHP Questions - Developers Q & A

    [...] opportunity to do something useful for once, by adding a typemap or anything. Otherwise eschewing getters and setters alltogether might be [...]


Leave a Reply



Back to top