Hacker News new | past | comments | ask | show | jobs | submit login

> There is no formal method in OO that tells you what is a sound design choice and what is not.

System architecture is hard. OO design is a set of principles that helps you design a system better by making it easier to maintain and modify. It does not tell you how you should model your objects. To come up with a good model is usually not straightforward.

In fact your example is not an issue specific to OO design. This is a general issue of relationships ('many to many') and there are a number of design principles to help (see database design principles as that's a typical scenario in databases).

> Where do you place this method? You need to add it to PartsSuppliers, because no one else is allowed to have private references to Partts

That's not true, but as you say, this is too vast a discussion.




I try to put it another way, because it is a much more general problem of OOP: If you have an object A that references an object B and object B references C and A wants to know something about C, we always have to go through B, regardless of whether we are actually interested in B or not. This is because C is part of the private state of B, and if A had a direct reference to C it could mutate C and would therefore break B's encapsulation.

> In fact your example is not an issue specific to OO design.

This is a specific problem with nested data structures. OO design leads to nested data structures to allow encapsulation. The relational answer to this problem would be to break everything up into flat sets of tuples that can be joined as needed, but if everything is just flat data, you can't have encapsulation.


But this is not a good example.

Either this should be modelled so that A can directly reference C to start with, or indeed A has to go through B but can do so to get a reference to C (this does not break encapsulation in itself, it depends on the specific relationships)

It's impossible to avoid nested data structures because these are simply the natural consequence of the system's complexity. For instance, a book is made of sheets, pages, chapters, sentences, illustrations, etc. entities with nested relationships.


> Either this should be modelled so that A can directly reference C to start with, or indeed A has to go through B but can do so to get a reference to C (this does not break encapsulation in itself, it depends on the specific relationships)

If A has a reference to C, B cannot, and if B has a reference to C, A cannot. To keep encapsulation intact, references between objects must form a tree. OOP depends on the partitioning of mutable state for maintainability reasons. There is no other way to keep this partitioning intact than to have a tree of objects.

> It's impossible to avoid nested data structures because these are simply the natural consequence of the system's complexity.

This is a purely conceptual view. But you don't have to query it that way at a logical level, or organize it that way at a physical level via memory references. HN comments, for example, are conceptually contained in their parent comments and also conceptually contained in the users who wrote them. In a relational database, on the other hand, the tuples would be contained only in their relations/tables. A query could then associate comments with users at runtime, but comments can be queried on their own, since they are not encapsulated in anything. In OO design, on the other hand, all access paths are baked into the object trees, making later, unforeseen changes to the software extremely difficult without taking shortcuts in the tree and thus destroying the encapsulation.


> If A has a reference to C, B cannot, and if B has a reference to C, A cannot.

That's not what encapsulation means, and again, it's up to you to come up with a model that makes sense.

> In a relational database, on the other hand, the tuples would be contained only in their relations/tables. A query could then associate comments with users at runtime, but comments can be queried on their own

Sure but they are still 'nested' by way of relationship. Of course you don't have to physically nest structures within structures. Both make valid OO implementations. Nothing in OO prevents you from querying comments on their own.


> That's not what encapsulation means

Then what does encapsulation mean? If encapsulation means that an object protects all of its private state behind methods, then another object must not be able to manipulate that private state. So if an object A holds a reference to another object B, then B's state becomes part of A's state and only A must be able to do things that change B.


OOP only strives to encapsulate private state (though don’t forget that too strict rules never make sense. In the end, every design pattern needs an escape hatch). All the methods of the object should modify these in a way that upholds the class invariants. In your example, B can easily be part of the “public state” of the object, or we can make even more gradual distinctions, like only B’s identity is relevant for A’s state. For example, if A only needs B as optional cache, its modification or even removal will not be a problem.


This concept of "public state" makes no sense to me. If the behavior of A, i.e. the implementation of A, depends on B, then changing the state of B will also change the behavior of A as a side effect. Otherwise, if B were "public state", then B would be nothing more than a glorified global variable and you would have exactly the free for all access that OOP is supposed to prevent.

So the only way to prevent this is that each object must have only one parent in the object tree, which coordinates all modifications to that object.

Regarding escape hatches: Yes, it's great to have them, but it's not so great when they are used all the time, either by accident because it's so easy to break OO rules, or on purpose because the object tree gets in the way when new requirements need to be implemented. Let's be honest here: The more mature an OO-designed project becomes, the more shortcuts there will be and the cross-connections aka "escape hatches" will turn the object tree into an object spaghetti.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: