Data Pull vs. Push OOP Approach

28,554

Solution 1

According to tell dont ask, push is better - or more OO. You don't want to query object for data so you can do something, you want object to do it, because he's the one who knows his data.

Related article about evil getters

Solution 2

I think the discussion here is kind of missing the crucial point about pulling and pushing and it is stuck on individual examples and cases.

Pushing : The advantage of pushing is that you know your data and you know what you are pushing. No component knows (or should not know) the data better than the component who owns the data, which will theoretically imply a better design and a more robust system.

Pulling : The only advantage I see in pulling approach is the component who pulls exactly knows when it should pull. It can initiate the conversation when it needs the data and no component knows (or should not know) when the data is needed than the component who needs it.

My conclusion on that is: whichever the component owns the transaction, it initiates the transaction. If you are retrieving data from an API, obviously the API client will own the transaction so will do a pull. If you are broadcasting a message than the broadcaster owns the transaction so it does a push.

Solution 3

As stated by other answers, neither push nor pull is better, but rather you should pick the one that best fits your design needs.

From here discussing whether an observer model should be push or pull based:

Who triggers the update?

The communication between the subject and its observers is done through the notify method declared in observer interface. But it can be triggered from either subject or observer object. Usually the notify method is triggered by the subject when it's state is changed. But sometimes when the updates are frequent the consecutive changes in the subject will determine many unnecessary refresh operations in the observer. In order to make this process more efficient the observer can be made responsible for starting the notify operation when it consider necessary.

For this pattern the determining characteristic is the frequency at which the data changes and then the corresponding rate at which the observers wish to receive that data. If the observers want the data at a slower rate than the subject generates the data (an example would be GPS on a phone, you don't need your position all the time, only when you have a specific use for it) then polling is more efficient. If the observers want the data as fast as the subject can produce it (a possible example would be a real-time stock ticker application), then push notifications are probably better.

Solution 4

It should not be any different in OOP (there may be something i have missed) but a pull approach is better.

The reason I say this is because of the recent trends in design patterns. Domain Driven Design and CQRS being some of the very prominent, they promote loose coupling which is a very good thing.

A object shouldn't care what another object does with it's data, it is not it's responsibility so to speak. The object should only make the data available and then the ones needing the data should fetch/pull it from that object. Look at event driven design.

It makes the object independent of the other objects and makes it more portable (don't have to change where it pushes to, since it will get pulled from).

TL;DR I would recommend pull'ing over pushing.

NOTE: all these different design patterns dosen't exclude each other, but coexist.

Solution 5

destination.Push(source)

  • Destination knows what and how to get data from Source
  • Destination must depend on Source, or
  • else Source must implement a provided ISource interface and depend on the provider (might be the Destination package)
  • The method has direct private access to Destination.

source.Pull(destination)

  • Source knows what and how to put into destination
  • Source must depend on Destination, or
  • else Destination must implement a provided IDestination interface and depend on the provider (might be Source package)
  • The method has direct private access to Source.

Select your solution by looking at the dependencies you want to have in your code.

If Source and Destination cannot depend on what's needed for the previous scheme, then you need the action to be performed by an external method that knows (depends on) both Source and Destination. It only has public access to both though.

If you need any virtual ISource to feed any IDestination then you need those interfaces to expose all the methods needed for an external method to perform the action.

If a single external method cannot perform the action on any ISource and any IDestination, then you might want to look at the Visitor pattern, the Visitor class performing all the particular actions on the specific Source1 and SourceX Destination1 and DestinationY.

Share:
28,554

Related videos on Youtube

Bunkai.Satori
Author by

Bunkai.Satori

Updated on July 09, 2022

Comments

  • Bunkai.Satori
    Bunkai.Satori almost 2 years

    When I design my system from scratch, I often face a dilemma whether my object should push information into another objects OR whether the objects should pull the necessary data from another objects.

    Is there anything like a standard in OOP design, that I should prefer data pull by objects, versus data push into objects?

    Can anyone experienced advise, whether one approach is better over the other from longer term viewpoint, or when the OOP structure/framework/diagram gets more complex?

    • Victor Sergienko
      Victor Sergienko about 13 years
      GoF design patterns consist of pretty specific problem statement and a solution. It's not generically reasonable to be less specific then GoF. Without the first part, any question makes little sense. And your question formulation is NOT related to C++.
    • Sandeep G B
      Sandeep G B about 13 years
      One of the thumb rules is never copy or cache data in multiple objects. Instead expose data as getter (property) which can be accessed using object reference. This way you just notify (Observer pattern) when something changes by passing object reference or just a notification. Rest of the access should be through the getter property.
    • Bunkai.Satori
      Bunkai.Satori about 13 years
      @Victor Sergienko: Hi, and thanks for your comment. You are perfectly correct, that my question is related to OOP in general. I will check GoF design patterns, to see whats in there.
    • RBT
      RBT about 9 years
      If the observed object is complex and the observer needs a hint, then go with push model. If the observed object is simple, a pull model will do. E.g. If the observed object is an employee with 20 fields and observer gets a notification from the subject that employee object has changed then it makes sense for observed object to PUSH the details of changed fields in a data structure(e.g key value pairs) instead of observer pulling whole data set and then making dumb comparisons with its previous state to know exactly what all fields changed. Choice should be driven by situation.
  • Bunkai.Satori
    Bunkai.Satori about 13 years
    @Izac Mac: +1 for good answer. Hi Izac, thanks for replying. To be honest, my intuition tells me, that pull approach is better than push approach. My logic behind this is, that a class should get a data when it asks for it, and therefore it will be avoided pushing data to some classes that do not need it. I know, that it might not be always possible to utilize pull approach, but we are considering cases with choice pull vs. push. I wish to keep this thread open for a while, to see if more answers appear.
  • Izac Mac
    Izac Mac about 13 years
    @Bunkai...accept answers if u think they make sense....and yes ur right u can't ALWAYZ use pull but as a good programming practice, u should try doing so... i personally make functions for respective classes that push data so that encapsulation is preserved.. also when u will get into polymorphism, my answer will make more sense.
  • Bunkai.Satori
    Bunkai.Satori about 13 years
    @Izac Mac: Thanks, Izac, for additional info.
  • Kirk Woll
    Kirk Woll about 13 years
    @Izac, don't pressure people into accepting answers to new questions. It's more than reasonable for the OP to await further answers to his question before deciding.
  • Bunkai.Satori
    Bunkai.Satori about 13 years
    @Kirk Woll: Thanks for your comment. I agree with you. I think, Izac's answer is good, but it is only one. I would like to see if another people have different opinions. Marking this thread as "Answerred with Accepted Answer" could distract people to put anything new in there. Thanks.
  • user229044
    user229044 about 13 years
    @Izac Please get into the habit of communicating professionally on Stack Overflow. Txt speak (u, alwayz, ur) is generally frowned upon here.
  • Bunkai.Satori
    Bunkai.Satori about 13 years
    +1 for very good answer. Thank you. Angel, what is your opinon on the approach, that objects should be as independent as possible, and therefore, if there is a choice, they should be responsible for updating themselves (pull method) instead of letting other objects to update them (push method)? This questions originates in my knowledge, that objects should be encapsulated and as independent as possible.
  • Bunkai.Satori
    Bunkai.Satori about 13 years
    Hi Kamil, +1 for valuable addition. I see here are trhee complete different reccommended approaches: 1. PULL is preferred, 2. it depends on situation, 3. PUSH is recommended. At the end of the day, maybe the middle way, where it depends on the particular scenario, will be the best choice.
  • Kamil Tomšík
    Kamil Tomšík about 13 years
    @Bunka.Satori: the question was what is better from OO point of view, and the answer is push, you don't want to publish internal data. Remember that 10 setters are thinner API than 1 getter.
  • Mecki
    Mecki about 12 years
    +1 for providing these two really interesting links. OO programmers should have read those, even if they decide to disagree in the end and use a different pattern. It will still influence their point of view.
  • Mecki
    Mecki about 12 years
    -1 as this answer somehow misses the real point of the original question, IMHO. Nobody asked if "getters" are a good thing or necessary, the original question was rather about a more abstract design pattern. If you read the links found in this answer stackoverflow.com/a/5855531/15809 you will see that actually push is much more "real OO programming" in many aspects because too much "pull" breaks the principle of data encapsulation.
  • Kamil Tomšík
    Kamil Tomšík about 12 years
    consider reading Hollub on patterns, you might like it too. If I could force programmers into something, it would be smalltalk - not as their major language but it's definitely worth of trying from the same reason you've already stated. OOP just makes sense there.
  • Izac Mac
    Izac Mac about 12 years
    its a matter of opinion.. but even in monolithic desktop apps.. i personally prefer pull approach for the reason that functions that respect the abstraction concept are less likely to push data then to pull data. Totally depending on the scenario but Angel i think that you will also agree that the first approach u should try is pull instead of push data ... it may screw up things .. but "PULL approach" won't screw up cause whatever structure or class ur using, ur less likely to make a blunder in one implementation file then sending from one and receiving from another class file.
  • Izac Mac
    Izac Mac about 12 years
    true...Push is more OO, but even u will agree that we prefer pull and use PUSH in only "NEED TO DO BASIS" cause we are less likely to screw up in pull approach then to push data cause 1)PUSH BASICALLY MEANS TO PUSH FROM ONE END OF CLASS OR OBJECT AND THEN "PULL" IT FROM ANOTHER < THEN PROCESS IT. 2)PULL means to just fetch data and process the object or data. so i still would say that pull is better.(BUT NOT ALWAYS POSSIBLE) :)
  • Kamil Tomšík
    Kamil Tomšík about 12 years
    I prefer push, really. It's not always possible (you're often limited by existing codebase/libraries). And it really does mean push, not "push-like pull". This is example of push. You tell your object to render itself "over there" and it can do it in abstract terms because of provided response builder. The very same thing applies even for streams, instead of returning toString() representation, you can implement writeOn(aStream), that way it could be push "all-the-way-down", depending on limits of your lang libs.
  • Kamil Tomšík
    Kamil Tomšík about 12 years
    you don't need to push real data, you can push lazy proxy
  • Fuhrmanator
    Fuhrmanator about 12 years
    Designing a class so it doesn't reveal its implementation is best and independent of push-pull. I disagree with the generalization that push is better. Also, did anyone else catch that the tell-don't-ask page says "in a recent book", which refers to a Smalltalk book from 1997. How old is that article?
  • Kamil Tomšík
    Kamil Tomšík about 12 years
    OOP was invented in 70s, so what? :-)
  • ralzaul
    ralzaul about 9 years
    this is not the point here, the question here is who should initiate the conversation of data transmission.
  • UmNyobe
    UmNyobe about 8 years
    I like a lot how you approached the question, in term of "what" vs "when"