8

Is there a name or a particular rule for objects that contain objects that contain... and so on. I'm working with a complex system that often has objects running 5-10 layers deep. One reason I'm hearing for why this is done is to pass a lot of data from server to client all at once, is there a better way to do this?

Edit: It seems that it is a combination of a few anti patterns. The Domain model should be cleaned up, and the following antipatterns are the smells: Train Wreck Pattern, and Everything but the kitchen-sink map

FooBar
  • 1,663
  • 2
  • 12
  • 19
  • 1
    I do not know if it is an antipattern. If you look at any ORM, you will find beans containing beans containing beans... – SJuan76 Nov 05 '12 at 08:52
  • 2
    A code with too many layers is called "lasagna code" :) – Adam Stelmaszczyk Nov 05 '12 at 17:00
  • 1
    We have a design pattern named "Chain of Responsibility pattern" for the scenario mentioned above. As long as one entity is responsible for taking care of only the next entity below it - http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern – Rockstart Nov 14 '12 at 05:09

4 Answers4

7

I don't know a name for this kind of object tree. But a well known anti-pattern is the Train Wreck Pattern which occurs when code uses excessive method chaining.

objA.getChildB().getChildC().getChildD()....getChildZ().performSomeAction();

It is a good rule of thumb to wrap all of

.getChildC().getChildD()....getChildZ().performSomeAction();

into an method on

objA.getChildB()

Let's call this method performSomeActionDeepDownTheObjectTree().

  • Wouldn't this cause unnecesary bloat in childB if the amount of calls grew? It seems that it might be better to create a specific data object containing the objects necessary and add the calls to this object to encapsulate the logic – FooBar Nov 05 '12 at 10:17
  • 1
    @FooBar You could do that. How to resolve the problem caused by this anti-pattern is left as an exercise to the reader :) –  Nov 05 '12 at 10:19
  • What if I can't change the methods/classes of any of A, B, C .. Z? – Quirk Jun 19 '18 at 13:30
5

This looks like a domain model gone sour (not an antipattern name, BTW :) It stems from the illusion that there is such a thing as a well-defined domain model. In reality, there are some aspects of the problem domain that can be elegantly modelled, but at the finer level of detail there are exceptions upon exceptions and special cases upon special cases, each specific to a single service method, that destroy this elegance.

The appearance of many nested objects is often the result of a continuous process of "grinding down" the domain model to ever finer granularities, in the hope that every instance variable may be reused in different contexts. There is a breaking point where the dogmatic imperative to reuse each and every domain attribute just stops making sense.

My way out of this is to stop trying to create a one-size-fits-all domain model and use objects specifically designed for each service call. These objects may rely upon some of the well-defined domain objects, but add any specific information separately and in a way that doesn't interfere with other service calls.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • Sounds like a good solution, I'll have to take a look at the domain model and see if I can clean it up and implement some new specific objects to avoid this – FooBar Nov 05 '12 at 10:20
3

The term is "object orientation" wherein you decompose large complex problems into smaller problems by defining classes of objects each of which encapsulates a small part of the problem. The way objects interact is by message passing and objects find other objects to pass messages to by starting with the objects they contain.

The larger and more complex the problem, the more work you have to do to decompose it into manageable pieces, so the more layers of objects you get. Sometimes small simple problems are decomposed badly into large numbers of objects, but that doesn't make object orientation itself an anti-pattern.


the main problem is simply that the data objects grow too large through nesting as well as including irrelevent data. Example: You're sorting birds and rather than a simple bird object you receive an object bird, containing feathers, beak, possibleParasites, air, possibleHousesNestsCanBeIn, and foodTypes, food types contains fruit, insects, worms, seeds, seeds contains oak, elm, thistle, possibleAnimalsThatCanEatSeeds etc etc –

The Everything but the kitchen-sink map anti-pattern is probably the closest fit.

Given a complex process with many complex rules, everything (business logic, related and unrelated procedures, etc) is shoved into the map.

The best way to solve this is with a filtering operation where you specify a strongly typed interface like interface BirdList extends Iterable<Bird> {} and the query system provides an implementation of that backed by just enough data to support that interface.

Your API could provide a number of different interfaces like BirdList and BirdFeedingHabitMap, BirdNestingHabitMap, etc. Clients can come up with a list of interfaces they need and the query system analyzes them, fetches the data, and uses proxy classes to assemble an implementation class that exposes the query results in a type-safe way.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • Naturally, I'm not arguing with that, I'm speaking about when you have objects, specifically data objects nested to the nth degree causing bloat of data and trouble with being able to access the correct data or even know what data is included upon retrieving an object – FooBar Nov 05 '12 at 10:18
  • While this can be a problem it is not the main problem, the main problem is simply that the data objects grow too large through nesting as well as including irrelevent data. Example: You're sorting birds and rather than a simple bird object you receive an object bird, containing feathers, beak, possibleParasites, air, possibleHousesNestsCanBeIn, and foodTypes, food types contains fruit, insects, worms, seeds, seeds contains oak, elm, thistle, possibleAnimalsThatCanEatSeeds etc etc – FooBar Nov 06 '12 at 06:12
  • @FooBar, is this data sent over the wire? Is there a way for you to say -- I require something that satisfies this interface and only want the data necessary to satisfy this interface? – Mike Samuel Nov 06 '12 at 14:59
  • @FooBar, please see my edit. The "Everything but the kitchen-sink map" anti-pattern describes what you're talking about. – Mike Samuel Nov 06 '12 at 15:02
  • Yes I would say that is a good description of what's happened, I think you got the right antipattern. For the solution though I think my needs will be what is suggested above, cleaning up the domain by trimming objects and creating custom ones for situations that exceed their scope. – FooBar Nov 06 '12 at 15:32
2

Objects containing objects containing… etc

is called a list and perfectly fine ;)

But you are right, long sequences of method calls is all but fine and a clean code smell called inappropriate intimacy.

Inappropriate intimacy can increase coupling, decrease cohesion, goes against the law of demeter and the rule tell, don't ask.

References: If you look up those terms, you will find a fantastillion many answers. Particularly good ones are Cohesion and Coupling and the book Agile Software Development, Principles, Patterns, and Practices by Robert C. Martin.

DaveFar
  • 7,078
  • 4
  • 50
  • 90
  • 2
    I don't think that is called a 'list'. A list is about things next to each other. –  Nov 05 '12 at 08:59
  • It's a list of `Object` - but it was more meant as a joke, because the objects containing objects .... is perfectly fine, only the long sequence of method calls isn't. I hope my answer clarifies that. – DaveFar Nov 05 '12 at 09:00
  • Not a list. A `House` object could contain a `Door` object, which could contain a `Lock` object, which could contain a `KeyHole` object and so on. That's hierarchy and not a list. – jlordo Nov 05 '12 at 09:17
  • @jlordo: ... and they are all of type `Object` – DaveFar Nov 05 '12 at 10:08
  • OP says nothing about the type of the objects. – jlordo Nov 05 '12 at 10:13