views:

315

answers:

6

Which would you recommend - a deep objects hierarchy (where each object hold a reference to it child objects), or flat objects (where you provide services to retrieve child objects)?

Let's assume that you are creating a database management application. You will have objects such as:

  • Server
  • Database
  • Columns
  • Views

Which option would you recommend:

  1. Each Server object holds a list of Database objects. Each Database object holds a list of Columns and a list of Views, etc.
  2. Each object is a "dumb" object, holding only its own properties, and you provide a set of services to retrieve the hierarchy, such as GetServerDatabases(Server), GetDatabaseColumns(Database).
A: 

I prefer the first approach. Although sometimes you might overengineer and create too granular classes, in general I think the tree like structure with each object having the intelligence is much better and object-oriented than a collection of "dumb" objects with a set of helper methods.

Naveen
+2  A: 

The second approach, I believe, matches the FlyWeight pattern: the objects don't aggregate their children directly, they just know how to get to them. When working with databases, you won't need all hierarchy present all the time, so in this context, I would prefer the dumb approach.

The FlyWeight can, however, be enriched with some caching, to avoid multiple retrieval of the same data.

xtofl
+2  A: 

If you're going on OO design principles, then both hold true. The second option is known as a coordinating object, and helps to prevent the state of your API/Core (whichever name you want) from being tampered with and breaking.

The 1st option would be how it is held internally, and you could optionally allow access to the Database's server property if you want to allow that.

My own preference would be to restrict any setters on the 4 objects, and force this through the coordinating/façade object (façade pattern). Let the Server offer its databases as a property, and so on down the chain.

As pointed out the Server.Databases property might be heavy. In which case this can be accessed via the coordinating object (the façade) instead.

So:

GetServers()
GetDatabases(Server)
GetColumns(Database)

and so on

Chris S
+2  A: 

If you work with OR-Mapping like Hibernate, than I would use definitely a deep object hierarchy.

Enyra
+1  A: 

You could do both as well. Deep model for Commands and flat model for querying. This is called Command Query Separation (CQS) and before applying I recommend to seek more knowledge about it.

Marek Tihkan
A: 

Your database schema should be whatever is appropriate for your needs. If you need referential integrity, and want to rely on some of the databases cascading features, and don't have big performance bottlenecks, your schema should reflect that. When using an RDBMS, you want to flatten your tables when you have good reasons to, otherwise, you end up with a lot of duplication or empty fields, which consume resources and can complicate your queries as they account for all the special cases -- it's much easier to use the set-based operations for which an RDBMS is designed. If you follow the approach of matching a table to each 'entity' in your domain, you should be ok.

For more complex entity models, +1 on CQS. In this case, you maintain a deep model for your commands and a separate, flattened version for your queries. If you don't want to follow CQS, you could flatten your deep model into DTOs in-memory. Otherwise, you can create a separate set of tables or views in your database from which to query. The second option seems to be more in keeping with CQS and you would likely have an easier time with some of the more complicated queries you may encounter.

lordinateur