开发者

When should an object be included as a member of another object, and when should it always standalone?

开发者 https://www.devze.com 2023-02-18 11:29 出处:网络
An example problem: On Stack Overflow, a question page shows a number of different answers. In displaying these answers, the site also gives information about the author of the answer. This means tha

An example problem:

On Stack Overflow, a question page shows a number of different answers. In displaying these answers, the site also gives information about the author of the answer. This means that although the number of badges a given user has has nothing to do with an answer in 开发者_如何学JAVAand of itself, that data still needs to be retrieved in order to display the page.

From what I can see, there are three different ways to go about pulling this view data in a model:

  1. A Post object could include a full User object as a member. The view would then access the user like this: $post->user->getReputation(). This seems cleaner, since a Controller could just request the posts and be done with it, but yet inefficient since a Post probably doesn't always need a full-blown User. I suppose it works well enough if the User object is relatively light, which it probably would be. The problem would then be that you would need to duplicate User retrieval code as part of the Post retrieval query.

  2. The Post object could hold just an ID for a User. When the Post, or Posts, are returned to the Controller, the Controller could then extract the unique User IDs from the returned set and pass them to a User factory. The returned User objects would then be passed along with the original Posts set to the View as a separate collection. The view could then grab user info using something like $users[$post->getUserId()]->getReputation().

  3. A hybrid approach: Include the User object inside the Post object, but have the unique id extraction and User retrieval as part of the Post retrieval method. i.e. Post::getPosts() would grab all relevant posts and convert them to objects with null User members, then it'd extract all user ids and pass them to User::getUsers(), then assign the Users to the relevant Posts before returning the set of Posts to the caller.

I guess what I'm getting at is, how do I know when an object needs to contain another object fundamentally? Is it unclean/a code smell to instead have such related objects returned separately, with neither object knowing the other has been retrieved. I'm leaning towards the separate retrieval concept - it seems the most efficient - but it really does feel like they're too related for that to make sense.


There is also a solution in between 1 and 2. You can have a lazy loading proxy for the user class. With this solution you can have best of both worlds because the proxy is interchangeable with the real thing so depending on the situation you can have the object itself or the proxy.

Edit: I'll try to explain this with an example.

Say that you have a view where you don't need user info, then you can instruct/configure your post factory to use the lazy proxy (see wikipedia)for the user which will only contain an ID. So no access to users is needed.

In another view you occasionally need to access user info but only for some posts, here again you instruct/configure your factory to include the lazy proxy for the user. But when you actually need access to the user info, you can access the proxy object that will then load the actual user object and redirect messages to it.

In yet another view you need both post and user info, so here you instruct your post factory to use actual user objects.


It seems to me that this is another case of dependency injection. A general enough idea that could help you.

DEPENDENCY INJECTION WIKI

Read something about the Inversion Of Control also.


why not add optional member to model to know informations?? you can ignore when you don't need and can use when you do need.

0

精彩评论

暂无评论...
验证码 换一张
取 消