event driven: how to specify the contract?

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: event driven: how to specify the contract?

Post by koen.h »

Jenk wrote:Then back to the observer pattern.. everything that can have one or more of its attributes change, must observe and accept notifications of change.. i.e.

Code: Select all

class Company {
  public $president;
 
  public function notify($notification) {
    if ($notification->getMessage() == "change president") {
      $this->president = $notification->getArg("president");
    }
  }
}
anywhere else...

Code: Select all

$president = new President(/* etc */);
$observable->notifyAll(new Notification("change president", array("president" => $president));
I'm not a fan of implicit dependencies. If the Company class listens to one event only you could make it excplicit:

Code: Select all

class Company implements IObserver{
    public function update(ChangePresidentEvent $event) etc // Spl uses update for the observer, notify for the observable
    public function changePresident(President $president) etc
}

class ChangePresidentEvent implements IEvent {
    public function __construct(President $president) etc
    public function acceptEventHandler(Observer $observer) {
        $observer->changePresident($this->president);
    }
}
 
interface IObserver {
    public function update(IEvent $event);
}
 
interface IEvent {
    public function acceptEventHandler(IObserver $observer);
}
I think this is cleaner because you get rid of the getters. Instead you implement the 'tell, don't ask' rule. Though I think my version isn't a pure observer pattern anymore. It gets rid of what I find ugly but I feel there is something missing.
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: event driven: how to specify the contract?

Post by Jenk »

direct access to properties is anything but cleaner. It's tight coupling, a fundamental "no" of good OO tbh.
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: event driven: how to specify the contract?

Post by koen.h »

Jenk wrote:direct access to properties is anything but cleaner. It's tight coupling, a fundamental "no" of good OO tbh.
?

There's no direct access to any properties. What do you see I'm not seeing?
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: event driven: how to specify the contract?

Post by Jenk »

My mistake, thought the ChangePresidentEvent was accessing president on something other than $this. I'd still not use an explicit type hint for event type though, tbh. It's just screaming "maintenance" later when you add extra events.
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: event driven: how to specify the contract?

Post by koen.h »

Jenk wrote:My mistake, thought the ChangePresidentEvent was accessing president on something other than $this. I'd still not use an explicit type hint for event type though, tbh. It's just screaming "maintenance" later when you add extra events.
I've mixed up two ideas I think. What I wanted to do was create an event class for every event so a class subscribing to the event could look at that class and know by the method signatures what they would be getting. But I see the 'changePresident' method the event calls is implicit. Need to fix my implementation.
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: event driven: how to specify the contract?

Post by Jenk »

It's just a lot of unnecessary work, for the sake of using type hints. Would be much simpler to just accept all events through one point and filter them.
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: event driven: how to specify the contract?

Post by koen.h »

Jenk wrote:It's just a lot of unnecessary work, for the sake of using type hints. Would be much simpler to just accept all events through one point and filter them.
I'm actually on the other side of this. I think the filter is too much work and too procedural. Creating a new event class is as easy as adding the filter part. The greatest advantage for me is that there is no doubt what you will be getting (contrary to getting something and needing to check if you get what you would like). But it's probably the same as the discussion about getting and setters I'm retaking here.
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: event driven: how to specify the contract?

Post by Jenk »

But there is also, on the flipside, the massive problem of what happens when you want to send a different type of event? You can't overload like in Java, and you'll find yourself having to rewrite half of your notification model to support multiple events per object. Unless you went the path of notifyPresidentChanged($newPresident).. but then, that's even tighter coupling than using the type hint to start with.

The point here is that all observers should receive all messages/notifications. That's the whole point of an observer, and further more, loose coupling. The Observer is to decide if it is relevant or not, not some outside influence. Using the type-hint or a method name like above, you're shifting the responsibility from $this to some other object.. which is a dependency and is bad!
Post Reply