Let's say I have two components talking to each other. The first one calls a "get results" function from the second one. How should I return the results?

For example,

SomeObject getResults(String name);

works fine but I am not sure whether it's the best way to go. This way both components seems coupled to the SomeObject type and I really want to avoid that. But what would an alternative be?

I could return the results as a List, but this transfer the responsibility of interpreting the results to the first component.

So, how should I do that? What is the best design approach for this kind of problems?

  • My admittedly biased opinion but if you can avoid introducing more data types into the codebase just to pass and return things around, and especially in a very limited context, avoid it. If using a List to return the results isn't too unwieldy for the client, go with that. It'll be easier to achieve stability that way, as in your code will have fewer reasons to change in the future the fewer user-defined types your code is coupled against.
    – user204677
    Dec 10 '17 at 21:14

There's no such thing as complete decoupling. To give meaning to the data that is returned from the function, you have to interpret it somehow, and that means having some sort of prior knowledge about the data.

Accordingly, you'll have to weigh the tradeoffs:

Tight coupling using DTO's

  • Type Safety
  • Ease of Use
  • High-performance
  • Proliferation of Data Types

Loose coupling using dynamic objects

  • Easier to interchange, interoperate and modularize
  • Simpler interface contracts
  • Lower performance
  • Greater complexity

If you wish, you can provide the greatest amount of decoupling by passing everything around encoded as text (i.e. serialized), and decoding it at the receiver end. But this comes at great computational complexity and cost, and is therefore normally utilized only at machine boundaries, where the benefits of a high degree of decoupling outweigh the costs.

Further Reading
Protocol Buffers


The idea of loose coupling is not to remove knowledge about other objects, it is meant to minimize that knowledge (hence loose coupling and high cohesion are often discussed together). Complete decoupling is usually not applied to domain objects (Java classes that hold data, e.g. Student, Car, Job, Result). The main point is to decouple behavior, so that different classes that process a domain object are independent.

An example: for domain object Student you may be implementing software that checks if student is eligible to graduate. This might involve checking if he has enough credit points and if all bills for credit points have been paid. Although both conditions deal with credit points, business-wise they check very different conditions. Hence you would like to build those checks separately from each other.

The way to reduce dependencies from domain objects is via inheritance. If, for example, you would like to return all Students that have not paid their bills, but you are using some generic system that also applies for Professors and Contractors then you make them implement a same interface, e.g. Student implements Payee. That way you can always return Payee instead of specific class.

In your example make SomeObject implement SomeSpecificInterface and return an instance of that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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