Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I just wanted to ask for your opinion on a situation that occurs sometimes and which I don't know what would be the most elegant way to solve it.

Here it goes:

We have module A which reads an entry from a database and sends a request to module B containing ONLY the information from the entry module B would need to accomplish it's job (to keep modularity I just give it the information it needs -> module B has nothing to do with the rest of the information from the read DB entry). Now after finishing it's job, module B has to reply to a module C if it succeeded or failed. To do this module B replies with the information it has gotten from module A and some variable meaning success or fail. Now here comes the problem: module C needs to find that entry again BUT the information it has gotten from module B is not enough to uniquely find the exact same entry again.

I don't think that module A giving more information to module B which it doesn't need to do it's job but which it could then give back to module C would be a good practice because this would mean giving some module information it doesn't really need.

What do you think?

share|improve this question

migrated from codereview.stackexchange.com Jun 20 '12 at 17:38

This question came from our site for peer programmer code reviews.

    
There is no code here, this isn't a code review. –  Winston Ewert Jun 20 '12 at 17:37
    
It wasn't me who posted here. Intially I posted on Stackoverflow and it got migrated here! Apearently the people who blamed me for not knowing that there were several sites and for posting on the wrong one stilll have to learn either... –  gekod Jun 25 '12 at 6:28
    
Stack Overflow really wasn't the appropriate site either. I don't see any evidence of the question having been migrated from Stack Overflow. Sorry for the ping-pong, but programmer.se is the best site for your question. –  Winston Ewert Jun 25 '12 at 23:03
1  
It's ok. I just didn't get why instead of just informing me of the existance of the other sites like code review and programmers, some people at stack overflow blamed me and down voted me immediately before migrating the post arguing it wasn't the correct place to post. I cannot know every available site on the internet... –  gekod Jun 26 '12 at 8:53
add comment

4 Answers

up vote 11 down vote accepted

Getting information from one part of a program to another is a constant battle and there is pretty much never a perfect solution.

I can see four possible solutions in a situation like this:

  1. Just go ahead and include the information that C needs in the call to B

  2. A calls C with all of the information and C calls B with just the information that B needs

  3. Put all of the information into a neutral object that both B and C can access and let each of them get what they need

  4. A calls B with just the information that B needs, B returns pass/fail, A calls C with information C needs (introduces dependency of A on C but removed dependency of B on C)

The "best" solution will depend on the circumstances that actually exist in any given situation.

share|improve this answer
9  
There is a 4th solution that may be applicable - A calls B with required information, returning success/fail, then A calls C. –  Glenn Rogers Jun 20 '12 at 14:14
7  
@Glen's is the proper solution: B's purpose is to make the calculation that fails or succeeds. A's purpose is to control the flow of control -- first to B and then to C. –  Larry OBrien Jun 20 '12 at 17:41
    
@LarryOBrien: While I would agree that Glen's solution is generally more proper, it is sadly true that the "proper" solution is not universally either easy (or even possible) to implement. I was attempting to provide solutions that would cover most situations. –  Donald.McLean Jun 20 '12 at 18:13
    
Sure, there are no universals, but Glen's solution (what is now your #4) is the one that is most in accord with software engineering principals. 1&2 pass unnecessary context and 3 extends scope unnecessarily. –  Larry OBrien Jun 20 '12 at 18:24
    
How much does module A actually need to know about the data item being handed around? Perhaps it would be better for A to fetch the item, pass it to B, receive the pass/fail from B, and then pass the item and the pass/fail to C. Doing it this way, A doesn't need to know anything about what B or C need internally from the object. –  John R. Strohm Jun 20 '12 at 20:29
add comment

module A giving more information to module B which it doesn't need to do it's job

Word "need" may be confusing unless one clearly specifies the needs. It is true that module B doesn't need this information to get the processing result, but it is also true that without this information, its results are useless for module C. In that sense, additional information serves a different kind of need - an integration need.

POSA 2 book presents a pattern intended to serve similar need - Asynchronous Completion Token:

This design pattern allows an application to demultiplex and process efficiently the responses of asynchronous operations it invokes on services. (quoted from POSA 2 patterns abstracts page)

Book presents a real life example to help understand the pattern: FedEx inventory tracking

...An intriguing real-life example of the Asynchronous Completion Token pattern is implemented by the inventory tracking mechanism used by the US Federal Express postal services. A FedEx Airbill contains a section labeled: 'Your Internal Billing Reference Information (Optional: First 24 characters will appear on invoice).' The sender of a package uses this field as an ACT. This ACT is returned by FedEx (the service) to you (the initiator) with the invoice that notifies the sender that the transaction has completed. FedEx deliberately defines this field very loosely: it is a maximum of 24 characters, which are otherwise 'untyped.' Therefore, senders can use the field in a variety of ways. For example, a sender can populate this field with the index of a record for an internal database or with a name of a file containing a 'to-do list' to be performed after the acknowledgment of the FedEx package delivery has been received.

You see, above example is quite close to what you describe. Guys "in the middle of FedEx chain" may say they don't really need billing reference, all they need to know is delivery address. But sender may use it when they need to be notified about transaction completion. That's an integration kind need.


For the sake of completeness note, there's an approach avoiding need to pass the "identification" info to module B. Module B could return its results to module A from synchronous blocking call. Upon return, module A could "enrich" obtained results with whatever additional info and pass it further to module C.

This way is not necessarily better than yours - for example, it loads module A with additional burden of knowing about module C, which isn't the case in your approach. That's why above answer doesn't dive into what approach to choose and when and instead, simply assumes that passing control from A to B then to C has been preferred for whatever reasons.

share|improve this answer
add comment

If B can't do its job (which includes telling C pass/fail) then A isn't really giving it all of the information it needs, is it?

Either add the info, or make that no longer part of B's job.

share|improve this answer
    
As good as I think Donald's suggestions are, this was my first thought after reading the question. –  shambulator Jun 21 '12 at 14:48
add comment

I agree with Larry OBrien than the best solution is probably to have A call B, then when B returns, A calls C.

If you really can't do that, I'd consider having A pass an opaque handle to B, which B then passes to C. C can then pass that back to A to get access to the information it needs.

In a typical implementation, A would cache the information, and the handle would really be something like a hash value or an index into a table. Assuming the data is no longer needed after being passed to C, A would also flush the data from the cache after passing it to C in response to being accessed via the handle.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.