Get and Set questions

Thanks for the pep talk!

Since this thread is mushrooming, feel free to hope over here to my related question on what classes do I need, and what data between classes and communications between classes makes sense.

As to your original question I would suggest this: treat getters and setters as fully valid constructs but when designing objects keep the tendency to have them do stuff instead of getting and setting their internal properties.

What do you mean by “have them do stuff”??

TomTees

That was a good article except I only got half-way through it before it was over my head.

And, yes, I think what you wrote, TomB, is what I was trying to recall.

My post has started a good discussion, and it leads to my bigger question/problem…

Where do I begin?!

And who do I listen to?!

Clearly, there are a lot of different approaches and opinions. And I have to be careful because this is like Michael Jordon and Larry Bird debating the finer points of basketball when I just want to learn how to play the game?!

I want to build an e-commerce site.

I do not want to buy one. And I don’t want to configure one either.

(If you wanted to learn to drive, hiring chauffeur or watching your friend drive isn’t the way to learn.)

It is my belief that if I break the problem down into smaller pieces, it is very attainable.

In fact, a good portion of the hard part is already done —> sketching the e-commerce site out and writing out the process flows (using Use-Cases).

My only challenge now is learning how to take my design and write it out using PHP (and hopefully OOP).

Sorry to go off tangent, but it seems like the more I read and the more I ask for help the farther behind I get?! :frowning:

If I can get some help on creating a handful of reasonable classes, deciding what their contents will be, and how they will talk back and forth, then I should be okay.

The good news is I know exactly how our e-commerce site will look and work, I just need some help doing it in PHP and OOP.

I guess I went off topic…

TomTees

Thats when the double dispatch comes in.


class Point
{
  protected $x, $y;
  function accept(PointVisitor $visitor) 
  { 
    $visitor->visit($this->x, $this->y);
  }
}

class EchoPointVisitor implements PointVisitor
{
  function visit($x, $y) { echo '(', $x, ', ', $y, ')'; }
}

$p = new Point();
$p->accept(new EchoPointVisitor());

Getters are called accessors, setters are called mutators.

I try to avoid needing to use them.

Far better to tell an object to do something, rather than be manipulated by some outside source.

Trivial example:


class Point
{
protected $x;
protected $y;

function print() { echo '(', $this->x, ', ', $this->y, ')', "\
" }
}

Rather than


$p = new Point()
echo '(', $p->getX(), ', ', $p->getY(), ')', "\
";

If you do it like this


class Person
{
  private $age;
  function getAge()
  {
    return $this->age;
  }
  public function setAge($age)
  {
    if ($age > 140) throw new Exception("I don't believe it, no-one is that old");
    if ($age < 0) throw new Exception("Age must be a positive number");
    $this->age = $age;
}

That will give a warning that something’s going wrong.

I cant edit my post but what you’re actually doing here is Design By Contract, which is a completely different subject. However, in DBC you’d use assertions which get turned off in the live application, rather than exceptions which cant be turned off.

Yes, they are called accessor methods (as they give access to properties of an object).

And no, it’s by all means not bad to use them. In fact, IMHO, it’s bad not to use them.

This roots in the belief that everything should be well seperated from each other and debuggable. When an object is allowed to change a variable of an other object directly, it’s easy to loose track of where this happens, resulting in a debugging mayhem.

Another good reason to use getters and setters is that you can manage which values are allowed, and which are not. For example, if you have a Person class, and that person has an “age” property, like so


class Person
{
   public $age;
   // more code here
}

I could very well do


$p = new Person();
$p->age = 1000000;

Now, no-one lives to be a million, but the code won’t raise any problems if you do this, but IMHO it should. Also, I could give a person a negative age, which is just as much impossible.

If you do it like this


class Person
{
  private $age;
  function getAge()
  {
    return $this->age;
  }
  public function setAge($age)
  {
    if ($age > 140) throw new Exception("I don't believe it, no-one is that old");
    if ($age < 0) throw new Exception("Age must be a positive number");
    $this->age = $age;
}

That will give a warning that something’s going wrong.

Hmm that looks interesting and does work around the problem, but how well does it scale? I mean when an object has many properties it could get messy… and from a maintainability point of view doing something as simple as putting one extra property into the view means changing the HTML, the class which implements the interface, the interface itself and the function which passes the properties to the “visitor” (as you have called it there, is that the technical term?) rather than changing only the HTML. Seems like a lot of extra work from that point of view, imho.

What about complex objects? E.g. classic example, an “Order” object which links to a “Customer” object and a set of “Item” objects. I cant see how that works without getting very messy and splitting the HTML across lots of different functions.

I don’t fully understand it so perhaps I’m missing something vital here but it seems like a lot of work for little practical benefit.

getters/setters ARE public properties, just with an overly verbose implementation. They share all the same design issues. There are hundreds of articles on the subject. Here’s a good start: http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

edit: ScallioXTX’s code is a perfect example actually. You’re still accessing the $age property directly, only now you have exceptions being thrown at arbitrary points in the application

For a start, exceptions shouldn’t be used for validation. They should be used when the system cannot work with the given data.

Secondly, in the real world, this type of thing is rather cumbersome. Imagine the Person object is being populated from a form. By having an exception in the setter you can only present one error message at a time to the end user. Helpful. It also stops code excution so you cant show the form again.

I personally try to avoid using setters and getters. If a public property needs to be protected from bad or out-of-range data, then it should probably be avoided. One important thing I’ve learnt in the last few months, is to program for the language you’re using. Because PHP, like most object-orientated languages, doesn’t have any getter or setter mechanisms built-in, I try to avoid the need for them in my code. On the other hand, a language like C# which does have a built-in getter and setter mechanism, lends itself to heavier use of object properties.

On the same note, PHP is also a dynamic language, so it’s good to use this to your advantage when it comes to setters and getters. For example, I don’t hesitate in making public boolean properties. Even though I can’t guarantee that this property want be set to a non-boolean value, I can rely on PHP’s dynamic type conversion in my code. For example, the following is perfectly safe, even though the variable I expect to be set to a boolean value, is actually an array…


$boolean = array("chalk", "cheese");

if($boolean == true)
{
    // Do something
}

Some may argue that this approach could hide bugs. That could be considered a con to some people, but it’s important not to forget the pros of this approach, which is cleaner, simpler, less error-prone code. Programming is all about striking that balance, as I’m sure everyone would agree.

You can also take advantage of PHP’s inline type casting when your variable absolutely must be of a given type. E.g…


$string = 67.6;

if((string) $string === '67.6')
{
    // Do something.
}

Not a very good example, but it demonstrates my point. Inline type casting like this should only be rarely required. If you’re code absolutely requires a variable to be a specific type or set of types, and a setter/getter is the only way you can think of achieving this, then this is normally an indicator that you should possibly rethink your class. It’s sometimes not possible to avoid setters and getters completely, but use more as a last resort, than a preferred solution.

That’s my opinion anyway. Good design in one language, may not always be good design in another, and vice versa.

Classes should call other classes, if they couldn’t … well, I just don’t see how you would write code without classes calling each other.
However, classes shouldn’t set / get properties of other classes directly, for reasons described in my previous post.

That doesn’t count, there is no former_life_occupation property in the Person class :cool:

It’s not merely for debugging, it’s also to protect the integrity of the data. If you use setters and getters you can control what values are allowed for specific properties of a class, and that allows you to handle errors if something goes wrong.

That’s what the throw new Exception(“some message”) bit in the code of my previous post does :slight_smile:
See Exception Handling on Wikipedia for more info.

If you consider me most people, then yes :wink:
All kidding aside, using setters and getters is considered better practice than accessing properties in other classes directly.

The problem there, even obvious in that trivial example, is you’ve moved the display logic into the object. What if you want to display it differently? What if you want to display it in 2 different ways. Doing that makes maintenance and reusability a lot more difficult.

You’d end up with huge classes which contain all the possible view logic used by that object. Then you have issues with complex objects and views which need data from multiple objects which are otherwise unrelated.

Okay.

That doesn’t count, there is no former_life_occupation property in the Person class :cool:

Ha ha.

It’s not merely for debugging, it’s also to protect the integrity of the data. If you use setters and getters you can control what values are allowed for specific properties of a class, and that allows you to handle errors if something goes wrong.

So you do most or all data validation in your classes in the Set method?

That’s what the throw new Exception(“some message”) bit in the code of my previous post does :slight_smile:
See Exception Handling on Wikipedia for more info.

Oh, I think you left that out of your last post, actually.

If you consider me most people, then yes :wink:
All kidding aside, using setters and getters is considered better practice than accessing properties in other classes directly.

Okay.

TomTees

I wish I could remember what and where I read that there was some debate on this topic… :scratch:

I think it was that everything in a class should be private?

Or maybe it was that one class shouldn’t call another class?

Hmmm…

Another good reason to use getters and setters is that you can manage which values are allowed, and which are not. For example, if you have a Person class, and that person has an “age” property, like so


class Person
{
   public $age;
   // more code here
}

I could very well do


$p = new Person();
$p->age = 1000000;

Now, no-one lives to be a million, but the code won’t raise any problems if you do this, but IMHO it should. Also, I could give a person a negative age, which is just as much impossible.

(What about the fact that I was a Roman Soldier in my former life?!) :lol:

If you do it like this


class Person
{
  private $age;
  function getAge()
  {
    return $this->age;
  }
  public function setAge($age)
  {
    if ($age > 140) throw new Exception("I don't believe it, no-one is that old");
    if ($age < 0) throw new Exception("Age must be a positive number");
    $this->age = $age;
}

That will give a warning that something’s going wrong.

So you should do debugging in classes that way, or is that just for during development?

(I thought you were supposed to use some fancy “exception” thing when writing OOP classes?)

Back to the original post…

So it sounds like most people use Setters and Getters and that is a fairly acceptable way to code my classes?

TomTees

http://stackoverflow.com/questions/565095/java-are-getters-and-setters-evil

Getters and Setters are not evil, but they can be. As with a lot of OOP methodologies, it’s a balancing act.
For example, decoupling is good, it helps maintain Single Responsibility Principle - but can lead to unwanted class proliferation. If you’re writing a mini framework etc. how far do you need to go?
On the other hand, strong coupling makes your system brittle/inflexible, but in some cases it’s a better tactical decision given the context of the project.
Design patterns require design decisions…

I think what you may have read, TomTees, is about the magic methods, __get and __set.

I don’t use them personally, but that’s simply because people here don’t like them. I can’t even remember the reasons - so if anyone DOES know, let me know :stuck_out_tongue:

Every object should have control of its own state. Public properties do not support this practice and expose state change without allowing the object being able to regulate it. I never use public properties for that reason. Restricting direct access to the objects state to methods also makes things much easier to debug and read.