问题
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?
回答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
回答2:
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.
回答3:
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.
回答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.
回答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.
回答6:
The answer depends on your architecture goals, in other words there is no general solution.
In a client server architecture you likely will have a layered system on the backend where objects pull state from other objects. That means only certain "services" will in the end update the state of an object. Example: creating a new object, updating a field of an object etc. (Like adding a new order item to the total order).
In monolithic desktop application it might be completely different. You likely use "Model-View-Controller" variations and observer patterns etc. In this case you push info e.g. to the UI.
回答7:
Usually 'pulling data' means you're doing an ajax call and running a callback upon its successful response. This isn't bad, but it can be overly intensive if you're checking for data updates and are thus doing it on an interval.
But in the context of an online web application, an alternative to this is push with long polling. Since long polling isn't terribly different from the first method, I propose you do the following:
Create a long polling method that pulls data from a a semi public push url endpoint (aka a webservice for pubsub), and then update everything that needs to be updated via using a publisher-subscriber design pattern in your client. That way your updates are more decoupled from the data source.
Here's a white paper that was written on this topic by IBM. http://www.ibm.com/developerworks/library/specification/ws-pubsub/
回答8:
The word push/pull is relative. There will be a pusher who has data and there will be a puller who needs data. If we actually store the data in a neutral place and not inside push-er/pull-er, many possibilities raise that suits a given problem at time.One updates the data when he has it(send notification if necessary) and the other pulls the data at his convenience. Many design patterns, MVC, Observer, Command, etc fall in place to handle the scenario.
回答9:
First, the general guideline clearly is: objects are data and behavior. This encourages less getters and so less pulls by providing methods which do something with the internal data.
Alone "push is better" (in the accepted answer) can't quite work as a push-operation in some class can require a new pull at the pushed object. Instead the best practice should be adding the push operation where it fits the abstraction best. This can even lead to a new more abstract class / composition of classes (see Object-Oriented Design Heuristics, Riel, 1996, p. 37 f.).
回答10:
From my perspective... As a desktop application developer using mvc, there is a delicate balence where by you push data when available to your model objects, then based on logic in the model (timers/ asynchronous events/ notifications) then the data is pushed out to the controllers and in turn to the view... The ui interactions can go either way depending on preference, they can fire a refresh or update message which tells the controller it needs to do something, or it can specifically push data into the controller and often in turn the model.
Of course this is simplified and confounded by real world scenarios but just having enough wherewithal to intend to do it a particular way can go a long way.
回答11:
@kamil-tomsik What do you think on a client server model, where you have hundreds of client who are observers, but they don't need same data, so if you push you have to send them all the data you want to share, but some of them, don't need it. Isn't it slow down the communication?
回答12:
From a design perspective, the data pull is always a better approach. The reason being that whatever information needs to be fetched, you're better off making functions in classes that returns those values instead of pushing information, which is not wrong but may complicate the outputs hierarchy when you are using polymorphism and advanced OOP concepts. Hope this answers your question.
来源:https://stackoverflow.com/questions/5792966/data-pull-vs-push-oop-approach