Page 3 of 3
Re: event driven: how to specify the contract?
Posted: Fri Aug 21, 2009 12:26 pm
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.
Re: event driven: how to specify the contract?
Posted: Sun Aug 23, 2009 9:09 am
by Jenk
direct access to properties is anything but cleaner. It's tight coupling, a fundamental "no" of good OO tbh.
Re: event driven: how to specify the contract?
Posted: Sun Aug 23, 2009 10:13 am
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?
Re: event driven: how to specify the contract?
Posted: Mon Aug 24, 2009 3:44 am
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.
Re: event driven: how to specify the contract?
Posted: Mon Aug 24, 2009 3:58 am
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.
Re: event driven: how to specify the contract?
Posted: Mon Aug 24, 2009 4:03 am
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.
Re: event driven: how to specify the contract?
Posted: Mon Aug 24, 2009 5:44 am
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.
Re: event driven: how to specify the contract?
Posted: Mon Aug 24, 2009 6:31 am
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!