I am learning the basics of software engineering independently.
And there's something I did not understand about the observer design template.
I have this diagram, in this diagram I marked what each part says, whether it is an observer, subject, concreteObserver or adapter.
From this chart I did not understand if it is a model of push or pull.
In my opinion it's a pull, but I'm not sure.
I think it's Pull, because we inform our Observers that there was a change, and the Observers go and check what the change was and interrogate the subject's state.
I would be happy if you could help me.
Clearly the ColourHandler is a Subject and the ColourSelectors are its Observers. Colour itself is a simple data structure. I have no idea why it would have a set_colour() method. An enum would be sufficient. Adapter is a separate design pattern, unrelated to Observer.
No implementation of the update() method is shown; however, we can see it takes no arguments. That is a strong indication of a pull model: the ColourSelectors must query the ColourHandler to determine the new Colour. Another indication is the circular dependency between Subject and Observer. In a push model, the Observer needn't be coupled to the Subject.
Also see the GoF description of push vs pull.
Related
I've noticed that my dependency injected, observer-pattern-heavy code (using Guava's EventBus) is often significantly more difficult to debug than code I've written in the past without these features. Particularly when trying to determine when and why observer code is being called.
Martin Oderski and friends wrote a lengthy paper with an especially alluring title, "Deprecating the Observer Pattern" and I have not yet made the time to read it.
I'd like to know what is so wrong with the observer pattern and so much better about the (proposed or other) alternatives to lead such bright people to write this paper.
As a start, I did find one (entertaining) critique of the paper here.
Quoting directly from the paper:
To illustrate the precise problems of the observer pattern,
we start with a simple and ubiquitous example: mouse dragging.
The following example traces the movements of the
mouse during a drag operation in a Path object and displays
it on the screen. To keep things simple, we use Scala closures
as observers.
var path: Path = null
val moveObserver = { (event: MouseEvent) =>
path.lineTo(event.position)
draw(path)
}
control.addMouseDownObserver { event =>
path = new Path(event.position)
control.addMouseMoveObserver(moveObserver)
}
control.addMouseUpObserver { event =>
control.removeMouseMoveObserver(moveObserver)
path.close()
draw(path)
}
The above example, and as we will argue the observer
pattern as defined in [25] in general, violates an impressive
line-up of important software engineering principles:
Side-effects Observers promote side-effects. Since observers
are stateless, we often need several of them to simulate
a state machine as in the drag example. We have to save
the state where it is accessible to all involved observers
such as in the variable path above.
Encapsulation As the state variable path escapes the scope
of the observers, the observer pattern breaks encapsulation.
Composability Multiple observers form a loose collection
of objects that deal with a single concern (or multiple,
see next point). Since multiple observers are installed at
different points at different times, we can’t, for instance,
easily dispose them altogether.
Separation of concerns The above observers not only trace
the mouse path but also call a drawing command, or
more generally, include two different concerns in the
same code location. It is often preferable to separate the
concerns of constructing the path and displaying it, e.g.,
as in the model-view-controller (MVC) [30] pattern.
Scalablity We could achieve a separation of concerns in our
example by creating a class for paths that itself publishes
events when the path changes. Unfortunately, there is no
guarantee for data consistency in the observer pattern.
Let us suppose we would create another event publishing
object that depends on changes in our original path, e.g.,
a rectangle that represents the bounds of our path. Also
consider an observer listening to changes in both the
path and its bounds in order to draw a framed path. This
observer would manually need to determine whether the
bounds are already updated and, if not, defer the drawing
operation. Otherwise the user could observe a frame on
the screen that has the wrong size (a glitch).
Uniformity Different methods to install different observers
decrease code uniformity.
Abstraction There is a low level of abstraction in the example.
It relies on a heavyweight interface of a control
class that provides more than just specific methods to install
mouse event observers. Therefore, we cannot abstract
over the precise event sources. For instance, we
could let the user abort a drag operation by hitting the escape
key or use a different pointer device such as a touch
screen or graphics tablet.
Resource management An observer’s life-time needs to be
managed by clients. Because of performance reasons,
we want to observe mouse move events only during a
drag operation. Therefore, we need to explicitly install
and uninstall the mouse move observer and we need to
remember the point of installation (control above).
Semantic distance Ultimately, the example is hard to understand
because the control flow is inverted which results
in too much boilerplate code that increases the semantic
distance between the programmers intention and
the actual code.
[25] E. Gamma, R. Helm, R. Johnson, and J. Vlissides. Design
patterns: elements of reusable object-oriented software.
Addison-Wesley Longman Publishing Co., Inc., Boston, MA,
USA, 1995. ISBN 0-201-63361-2.
I believe the Observer pattern has the standard drawbacks that come with decoupling things. The Subject gets decoupled from Observer but you cannot just look at its source code and find out who observes it. Hardcoded dependencies are usually easier to read and think about but they are harder to modify and reuse. It's a tradeoff.
As to the paper, it does not address the Observer pattern itself but a particular usage of it. In particular: multiple stateless Observer objects per single object being observed. This has the obvious drawback of the separate observers needing to synchronize with each other ("Since observers are stateless, we often need several of them to simulate
a state machine as in the drag example. We have to save
the state where it is accessible to all involved observers
such as in the variable path above.")
The above drawback is specific to this kind of usage, not to the Observer pattern itself. You could as well create a single (stateful!) observer object that implements all the OnThis, OnThat,OnWhatever methods and get rid of the problem of simulating a state machine across many stateless objects.
I will be brief because I'm new to the topic (and didn't read that specific article yet).
Observer Pattern is intuitively wrong: The Object to be observed knows who is observing (Subject<>--Observer).
That is against real-life (in event-based scenarios). If I scream, I have no idea who is listening; if a lightening, hits the floor... lightning doesn't know that there is a floor till it hits!. Only Observers know what they can observe.
When this kind of of things happen then software use to be a mess -because constructed against our way of thinking-.
It is as if and object knew what other objects can call his methods.
IMO a layer such as "Environment" is the one in charge of taking the events and notifying the affected. (OR mixes the event and the generator of that event)
Event-Source (Subject) generates events to the Environment. Environment delivers the event to the Observer. Observer could register to the kind of events that affects him or it is actually defined in the Environment. Both possibilities make sense (but I wanted to be brief).
In my understanding the Observer Pattern puts together environment & subject.
PS. hate to put in paragraphs abstract ideas! :P
Observer pattern-
Assumption:
Out of the 10 items, the observer only wants to be subscribed to 3.
Subject calls a function of the observer to let him know that there
are some updates.
Now, is it subject's responsibility to send the updates pertaining to only 3 items to the observer?
OR
Subject can simply tell the observer that there are updates - go fetch whichever you want out of 10?
Which is the correct way out? Does it matter?
It's the Subject to keep a list of Observers who are interested in this subject, and notify these Observers by calling its update method.
Observer does NOT keep a list of subjects which it is interested in.
Based on this, when a subject is updated, the subject will call the update(..) method or something similar of those Observers in its list. subject can either encapsulate the changes in an object as a parameter of the method, Or pass the this object of this subject (observers get the interested data by calling subject's methods themselves).
I'd rather go with specific notifications about different events. Usually with push model. Like Hey, I just earned some money. Here is actual amount I have earned. Instead of Hey, something happened to me.. Latter moves all logic to clients (observers). Clients should verify what has changed and this verification logic will be duplicated if you have several clients. Actually if you don't have other observers, you don't need this pattern :)
Also specific notifications allow to subscribe only to events which clients are interested in. So, observers will not be bothered when something other happened (i.e. when subject watched a movie).
Now, is it subject's responsibility to send the updates pertaining to only 3 items to the observer?
OR
Subject can simply tell the observer that there are updates - go fetch whichever you want out of 10?
Which is the correct way out? Does it matter?
There is no absolute right answer here.
These are implementation choices, and in fact are mentioned in the implementation section for Observer in Design Patterns:
_6. Avoiding observer-specific update protocols: the push and pull models. Implementations of the Observer pattern often have the subject broadcast additional information about the change. The subject passes this information as an argument to Update. The amount of information may vary widely.
At one extreme, which we call the push model, the subject sends observers detailed information about the change, whether they want it or not. At the other extreme is the pull model; the subject sends nothing but the most minimal notification, and observers ask for details explicitly thereafter.
The pull model emphasizes the subject's ignorance of its observers, whereas the push model assumes subjects know something about their observers' needs. The push model might make observers less reusable, because Subject classes make assumptions about Observer classes that might not always be true. On the other hand, the pull model may be inefficient, because Observer classes must ascertain what changed without help from the Subject.
_7. Specifying modifications of interest explicitly. You can improve update efficiency by extending the subject's registration interface to allow registering observers only for specific events of interest. When such an event occurs, the subject informs only those observers that have registered interest in that event. One way to support this uses the notion of aspects for Subject objects. To register interest in particular events, observers are attached to their subjects using
void Subject::Attach(Observer*, Aspect& interest);
where interest specifies the event of interest. At notification time, the subject supplies the changed aspect to its observers as a parameter to the Update operation. For example:
void Observer::Update(Subject*, Aspect& interest);
If it makes more sense in your situation to use the push model, so the subject has a bit more knowledge of the observers' needs, and to use an aspect model so that the observers can register interest in particular portions of the subject's data, go for it!
I usually prefer to use the pull model and accept that the observer has a bit of detailed knowledge of the subject (it's simpler to implement), but what you're proposing is probably fine in your situation.
I have to to find solution for the following problem :
I have a lot of model objects. Some model objects depend on other model objects. When the referenced model object changes dependents must be invalidated. I need to store list of my currently invalidated objects, so I can show it to the user and give him a chance to regenerate the objects if he wants to do that. The problem is how would I go with organizing and storing which dependencies an object has, and how to give and receive information when some object changes / become invalidated.
Someone can give idea , or maybe some similar pattern exists for this problem
Sounds like you need the Observer pattern:
The observer pattern (aka. Dependents, publish/subscribe) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
I have a fairly complex iphone application that has many asynchronous processes occurring. To deal with this I'm making heavy use of NSNotification Center. My question is what is the "best practice", if such a thing exists", for registering the notifications? Right now they sprinkled through my code in a hap-hazard way. I'm about to go to production and I want it cleaned up. I though about having a "registerNotifications" method in viewDidLoad of the main view which obviously registers all notifications in one shot. Does this sound reasonable? If not what would be the preferred way of dealing with this. Thanks in advance for your help!!
Putting all the notifications in one object destroys encapsulation and that is bad. You make one objects notification operations dependent on another object working properly. It will actually be a nightmare tracking all that. It is also backwards to the entire of purpose of notifications which is to create a decentralized and modular messaging system.
Notifications shouldn't be "sprinkled throughout the code" but they should be managed solely by the objects that receive them. If you use a great deal of notifications you might need to create a class with dedicated methods for handling multiple notifications and then have your other classes inherit from that class. That way you get automatic management.
One of the big mistakes people make with notifications is that they register controllers when they really need to register their data model. For example, suppose you're downloading some data from a URL and you want to update the interface as it progresses and/or when it ends. If you have multiple views in your UI and you register controllers, then every view has to manage a notification (of which there may be more than one.) However, if you set up the shared datamodel to receive the notification you need only have a maximum of two notifications. One will go to the datamodel so the datamodel can update itself and then you can have the datamodel issue a generic notification for any listening views to update themselves from the datamodel.
Making your view controller dependent on the datamodel simplifies design greatly in all cases.
An object should register itself as an observer of the notifications it is interested in. The best time to do it is when the object becomes interested, otherwise you have to deal with notifications when you don't want them.
In this text I read
Be alert for a component that is just
a glorified responsibility. A
component is supposed to capture an
abstraction that has a purpose in the
system. It may happen that what
appears at one moment as a meaningful
component is really just a single
responsibility left on its own. That
responsibility could be assigned to a
component.
This confuses me. If a class should have only one reason to change, it seems like it should have one responsibility. But now it seems I'm taking this too narrow. Can somehow give an explanation of responsibility and reason to change in the context of responsibility based modeling? Can a class have more than two responsibilities and still have one reason to change (or the other way around)?
Read about Class-Responsibility-Collaboration modeling (or design)
http://www.agilemodeling.com/artifacts/crcModel.htm
http://alistair.cockburn.us/Using+CRC+cards
http://users.csc.calpoly.edu/~jdalbey/SWE/CaseStudies/ATMSim/CRCmodel.html
http://c2.com/doc/oopsla89/paper.html
A class may have several responsibilities. It always represents a single "thing".
The "one reason to change" rule doesn't apply to responsibilities. Period.
The "one reason to change" rule should be used as follows.
It doesn't mean "1". It means "as few as possible".
It applies to the "interface" or "underlying abstraction" or "concept" for a class. A class should encapsulate few concepts. When that the core concept changes, the class changes.
Many simple things are better than a few complex things. It's easier to recombine and modify simple things.
Inside every complex thing are many simple things trying to be free.
It's hard to define "simple", but "one concept" is close. "one thing to change" is also a helpful test for "simplicity".
Finally, "one reason to change" doesn't literally mean "1".
The way I understand it, the danger of "glorifying a responsibility to a component" means that you need to be careful to not translate responsibilities to system components directly.
For example, in an email system, the user may approach the system with the goal of initiating a message to a recipient. It's the system's responsibility to make this possible.
The user may also approach the system to read and reply to an email. It's the system's responsibility to make this possible, too.
But does this mean that there need to be two components "initiate new email" and "reply to email" in the system? No. A general "compose email" component would be able to handle both requirements.
So in this case, the component "compose email" is responsible for the user goals "initiate new mail" and "reply to mail". But it would only need to change if its core concept changes ("how emails are composed").
Look again closely at the following phrase by Cockburn: "A component is supposed to capture an abstraction that has a purpose in the system". A purpose in the system (reason to change) is not the same as the purpose of satisfying a user goal (responsibility).
To make the long story short: As to my understanding, a component ideally has one core concept. It may have several responsibilities. But as I see it, the one responsibility may not be assigned to more than one component.