$obj()->var syntax for accessors?

Hi TomB,

In this less than perfect Class, that was created to attempt to illustrate ways to reduce setter/getters, the describe() methods is coupled to the current fields only on this particular operation and not when I want to pass the Dog around.

In this case, I make it clear that we can only get a whole Dog, and it is not OK to call separate setters.

The describe() method is pretty messy, it does have too much display logic. I could create a render method and then have describe() (rename it too) compile raw results and tell render() to render it. Again the idea was to simply show how to get setters / getters out.

The double dispatch is a choice and does come with trade-offs. You have consistently demonstrated that you don’t like the trade-offs of using greater complexity, and each person has to form their view as to what trade-offs they want. Is better encapsulation worth more than diluting it; I think so, but you and others will have their own ideas. The fact is, that any method that involves getting setters / getters out involve greater complexity, maybe a reason that they are chosen so often.

There may be people in this forum that did/do not know about some of these techniques, so hopefully this discussion helps make the choices clearer?

Regards,
Steve

oh I’m not trying to argue or say one method is better than the other, but simply get my head around all the options :slight_smile: I just felt like I was missing something obvious when the articles linked to made it sound so easy and trouble free to remove getters… it’s not as simple as the first article linked to implied and that’s what confused me about it.

My approach is to give a class full control over its own data, as well as full flexibility.

If you want to give, for example, a record’s ID to an object, you can explicitly give that ID via:

$Object->Record = $Record->ID;

Or you could have a bit of flexibility:

$Object->setRecord($Record->ID);
$Object->setRecord($Record);

Though I make use of the magic functions to make it:

$Object->Record = $Record;

The object itself checks what’s going in and what goes out, but I don’t like making a mess of notation, so by default all properties are accessed in the standard way.

Not that different, and I dare say not that good.

  1. I should not be forced to call describe(): semi-constructor? And I agree with Tom, too messy.

  2. age() and dateDiff() are a smoke screen, so I won’t address them. :wink:

  3. isGoingGrey() === getGrey(). I’d even argue that isGoingGrey is a bit forced as a name.

  4. changeCollar() === setCollar(). Again, a different (forced) way of saying set: change.

I’m working on something today, to counter. :slight_smile:

I don’t mean to pile on, but I agree with itmitică and Tom. The describe method is doing templating in a class that otherwise handles application logic. If that’s the cost of avoiding getters, then that cost is too high. Using getters would actually be better. And the age, isGoingGrey, and changeCollar methods are still getters and setters even if you avoid the words “get” and “set”.

On an unrelated note, the dateDiff method is probably unecessary. You can use the built-in dateDiff.

Just to put what ServerStorm was hinting towards on the table and re-introducing some flexibility and separation of concerns. I’ve severely cut down the class for ease of demonstration:


interface DogRenderer {
	public function render($name, $age);
}

class Dog {
	protected $name;
	protected $age;
	
	public function dispatch(DogRenderer $renderer) {
		$renderer->render($this->name, $this->age);
	}
	
}


class MyDogRenderer implements DogRenderer {
	protected $html;
	
	public function render($name, $age) {
		$this->html = 'Name: ' . $name . ' Age: ' . $age;
	}
	
	public function output() {
		return $this->html;
	}
}


$dog = new Dog();
$renderer = new MyDogRenderer();
$dog->dispatch($renderer);
echo $renderer->output();

Which should remove some of the valid criticism noted above.

However, my issue still stands, adding a single field e.g. “weight” requires:

-Adding the protected property
-Extending the interface (we can’t modify DogRenderer as we don’t know where it’s currently used)
-Either adding a new dispatch method for the new interface to Dog
–Or adding some logic to the dispatch function to check which interface it’s been passed (of course, if php supported method overloading this wouldn’t be an issue)

Wheras with a getter or public property, you add the property and change the HTML. The former method is a maintainability nightmare, in my opinion.

Hi,

Yes there is still a need to get or set logic within an object. You are right that I could have called them getColour(), getAge(), setGetCollar(). Out of these the only public of them is setGetCollar(). The getColour() and getAge() are coupled to internal logic. this type of coupling does not break encapsulation; setGetCollar() does.

As far as the templating in an object that handles application logic, yup. In hind-sight it would have been best to do this in at least two objects on that handles the template and the other that handles the applicaiton logic. As mentioned earlier this was an attempt to build something that used some of the ideas and did not force people to worry about that part of it. Does not look as it has served the intended purpose, but still it should not diminish the idea that encapsulation still an important pillar in Object Oriented Methodology.

BTW thanks for the dateDiff() reference.

Regards,
Steve

Hi,

I am not sure if you know of or agree with Martin Fowler, but I can say that I know why he writes books like Patterns of Enterprise Application Architecture

He has some interesting ideas on what we’ve been discussing, not all support my angle in this discussion, so here are a few one page articles surrounding this topic:

http://martinfowler.com/bliki/GetterEradicator.html
/* Interace Publication */
http://martinfowler.com/ieeeSoftware/published.pdf

These and more articles can be found at http://martinfowler.com/tags/API%20design.html. His main site is www.martinfowler.com

Regards,
Steve

As promised, this is my fiddle modeling for today: http://i1054.photobucket.com/albums/s490/itmitica/itmitica-dog.png

Tomorrow it’s code day.

Feel free to ask a question or dismantle the model.

[QUOTE=itmitică;5127340]As promised, this is my fiddle modeling for today: http://i1054.photobucket.com/albums/s490/itmitica/itmitica-dog.png

Tomorrow it’s code day.

Feel free to ask a question or dismantle the model.[/QUOTE] Hi itmitică,

When I try to open your link I get the following error:

An HTTP error occurred while getting:[COLOR=#000000][FONT=Times New Roman][B]http://i1054.photobucket.com/albums/s490/itmitica/itmitica-dog.png[/B][/FONT][/COLOR]
Details: “Unable to contact target server after 5 tries.”.

Try this: http://img135.imageshack.us/img135/3747/itmiticadog.png

Ruff, Rufff… Spot fetch setters and getters… Good Boy! Spot don’t pee on encapsulation. Oh wait that’s not a cool cat, go ahead boy. (Dog wags tail obsessively).

I see were your positioned.

Thanks,
Steve

I’m trying to base our talk on an example so that we can actually talk specifics. I’m also going somewhere with all this, once the code is in place too. I figured I’d cut down the whole scenario to just one possibility and make classes design target that possibility, thus slimmer and clearer.

I’m not so sure why you’re saying I’m ruining encapsulation? Maybe you’re misinterpreting something? Like I said, feel free to ask a question or dismantle the model. I won’t mind.

Sorry, it was too lighten the mood a little;

Would you say you would normally favour constructor initialization or do you favour setter initialization?

In the articles by Martin Fowler, he makes a good point that if you add a setter for a new property or a new getter that are public that search and place is relatively easy. He also talks about how it is not normally a problem when the code stays in his team (or himself), but does affected people when he releases library code out for the public domain. Then if we adds or removes setters/getters he can’t use search and replace and therefore breaks other that use the older code base.

Have you every tried to write your objects to have very focused responsibilities and then based on the objects that you set with constructor initialization are composited within another object that makes use of their run() or like command?

Have you used traits to more effectively use inheritance?

Thanks for your work on this.

Regards,
Steve

It’s a clean and interesting example, for sure, but I’m not sure it solves the original concern. The original concern put forth by the article with the hyperbole title is that getters subtly break encapsulation by revealing a private member’s data type – which is true. If “age” was once a timestamp integer and now we want to change it to a DateTime object, we can’t do that without breaking backward compatibility, because even though “age” may be private, it’s data type isn’t. And the same problem exists with the renderer example, because the renderer class depends on “age” being a certain data type.

I see two competing design decisions here. If we ensure that all private members are fully private, data types and all, then the Dog class must handle every task that uses Dog data, including templating. Or if we ensure good separation of concerns, then we must extract data from Dog, one way or another, which will reveal data types. I don’t see how we can have it both ways, and if I had to pick the lesser of two evils, I’d say it’s better to have good separation of concerns.

I’d say constructor initialization. Normally.

I have part of my code finished… it goes there, but hardly still… but for a complete discussion about encapsulation and getters/setters on an example I think it’s better to finish it first. Anyway, here it is what I have so far:


// start of app

$earth = new World('Earth');

$dog_barking = new Sound(
    'barking', 
    'Spot', 
    array(
        'type'  => 'house',
        'owner' => 'John' 
    )
);

$earth->event( $dog_barking );


class World {
    protected $name;
    protected $event;
    
    protected __contruct ($_name) {
        $this->name = $_name;
    }
    
    public event( $_event ) {
        $this->event = $_event;
    
        if ( $this->event->location['type'] == 'house' ) {
            $this->man = new Man( $this->event->location['owner'] );
            $this->man->alert( $this->event->name, $this->event->source );
        }
    }
}


class Sound {
    protected $name;
    protected $source;
    protected $location;
    
    protected __construct( $_name, $_source, $_location ) {
        $this->$name = $_name;
        $this->$source = $_source;
        $this->location = new Location($_location);
    }
}

Feel free to ask a question or dismantle this one too.

Hi Jeff,

What about standardizing the render interface in each object that needs to play together. So we have a public method render() on each object. This render method does not take any parameters. We tell each object to render its’ state. In the most simplistic form we could put each object in an array and issue the render() method. Each render() method could have their own details implemented and dictated by what each class needs to do. The logic inside could be changed by a little or lot and as long as they are wired to the render() method it would create a data output suitable for the medium (such as a web page)? This keeps the encapsulation, and adheres to a strict interface. In this way the Private Objects would likely have Model Contoller and View?

Steve

This has already been done in frameworks that use different templating systems.

One way they do it is like this:

  • the main framework on one hand, with a view property and a corresponding render() method
  • the “original” view framework on the other hand, with a parseHTML() method, for example
  • an interim view class between them, that takes the place of the view property and transforms the render() method for the main framework to the parseHTML() method or whatever method the “original” view framework has assigned for outputing

[QUOTE=itmitică;5127411]This has already been done in frameworks that use different templating systems.

One way they do it is like this:

  • the main framework on one hand, with a view property and a corresponding render() method
  • the “original” view framework on the other hand, with a parseHTML() method, for example
  • an interim view class between them, that takes the place of the view property and transforms the render() method for the main framework to the parseHTML() method or whatever method the “original” view framework has assigned for outputing[/QUOTE] I see… that was not exactly what I was thinking, more like:

class Dog {
  /* private things */

  public function render(){
    /* My way of rendering myself */
  }
}

class Human {
  /* private things */

  public function render(){
    /* My way of rendering myself */
  }
}

$animals = array( 'Dog' => new Dog(), 'Human' => new Human());


Some where in the webpage


<div>
<?php
   $animals['Dog']->render();
?>
</div>

Some where else in the webpage


<?php
   $animals['Human']->render();
?>

or


foreach($animals as $type => $animal){
    $animal->render();}

The problem here, though, is that you’re still doing templating inside the Dog class. What if there’s more than one way to render a dog? What if you want to render a short snippet for a dog list page, or full content for a dog detail page, or what if you want to render to JSON format, or XML, or what if you want to render an email message, or what if you want to render all those things but with multiple themes? Suddenly the Dog class is taking on far too much responsibility and knows far too much about the application.