Showing posts with label design. Show all posts
Showing posts with label design. Show all posts

2011-11-16

Modeling The Real World vs. Designing Software

Technikmuseum_Speyer_12I started writing a response to comments on a previous blog post, and it turned out long enough to become its own post. The question was on whether you should relationships in the "real world" to decide on relationships in your object-oriented designs.

"Is-a" and "part-of" are concepts from object oriented analysis, where you try to model "the real world" in terms of classes and objects. That is, by looking at the problem you are trying to solve, you could come to the conclusion that a customer "is-a" person, and that a street name is "part-of" an address.

In the early days of object orientation, it was assumed that you could simply transfer the relationships you found in that analysis directly into your design for good results.

There are (at least) three reasons why this doesn't generally work well, in my experience:

  • when we analyze the "real world", we typically model the problem space. When we design software, we model the solution space. Although there are often similarities between the two, there is no direct mapping - in fact, finding a good model for the solution is the most creative (and important) act in developing software. Assuming that an "is-a" relationship in the problem space will directly translate into inheritance in our solution space needlessly restricts our creativity, and thereby leads to inferior solutions.

  • for me, the primary goal of software design is to manage dependencies in the design, so that the resulting system is maintainable and extensible (because successful software is software that will need to be changed). As a consequence, there are forces working on our designs that don't exist in the "real world", and therefore considering just "real world" relationships won't help managing those forces. Just take the famous "a circle is an ellipse" example: while true in mathematics, depending on what you need a system to do, reflecting this relationship in your design can violate Liskov's Substitution Principle, and thereby lead to brittleness and unnecessary complexity. That is, a relationship that is absolutely natural in the problem space leads to problems when transferred as-is into the solution space. Another example: both a customer and an administrator are persons, but that commonality could be totally irrelevant to the solution of your problem, and then modeling it in your design would be a waste, at best.

  • in the English language, there is no unambiguous rule about when to use which phrase, anyway. Yes, you could say a customer "is-a" person. You could as well say that personal information is "part-of" a customer. Or that a person "has-a" role of being a customer. It can even make sense to say that "a person is a customer". So you really can't use natural language semantics to decide which relationship to use in your code.

So, using those relationship names doesn't really take the burden off your shoulder to choose wisely which relationship makes the most sense in your specific case. And an experienced designer will - whether explicitly or by gut feel - choose the relationship that leads to the most SOLID design. and he knows how to refactor to a different relationship when his understanding of the forces in the code changes.

2010-08-23

The Shu Ha Ri of Inheritance versus Composition

Tauziehen
For ages now, there is an ongoing discussion (to not say war) in the OO communities on wether it makes sense to prefer Composition over Inheritance or not.

My personal impression is that a lot of the heated debate stems from confusing advice given to beginners with what the experts do. A useful mental tool I like to use in occasions like this is the concept of Shu Ha Ri. Here is how I currently think about it:

Shu

You are (relatively) new to object oriented design. Inheritance is rather easy to understand, polymorphism a little bit more abstract. Inheritance is easy to do, composition a lot more work, or so it seems. It's likely that you are overusing inheritance, and that you could benefit from making more use of composition. That's fine, it's the usual learning step you have to take. Once you experienced how inheritance works (and where the problems lie), it's good advice to favor composition over inheritance, so that you can learn what the pros and cons of that approach are.

Ha

You have experienced the perils of overusing inheritance. You have experienced the flexibility that composition brings you - and where investing into composition actually doesn't seem to pay back much. It's time to start experimenting with a balance of inheritance and composition, and to find your own rules of when to use which.

Ri

Thinking in terms of inheritance versus composition doesn't make much sense to you. You know that both are just tools in your quest of producing maintainable, SOLID code. And you can easily refactor code from using inheritance to composition and back on a whim, so why make a fuss about it? Just use whatever your gut tells you makes sense at the moment.

2009-07-23

When to Introduce an Interface (in Java code)

TG 2009 - CC Euro setupThis is an answer to a question asked at Java Ranch: "How often should classes be programmed to an interface?" As this question gets asked regularly, I thought I'd "archive" it here...
I basically introduce an interface for five different reasons:
  • I want to mock an object for a unit test
  • a client only needs to depend on a small subset of the operations of a class (and for some reason, I can't/won't break down the class into smaller ones) (Interface Segregation Principle)
  • to invert the dependency between two modules (Dependency Inversion Principle)
  • to use polymorphism with classes that aren't related by a common superclass
  • I need to publish an API to a third party
In all other cases, I find that with modern tools it's so easy to introduce an interface after the fact - once I feel the need for it -, that introducing it "just in case" creates more disadvantages than advantages.

2008-02-27

You *Are* Gonna Need A Good Design

Kabel-Wirrwarr entdeckt bei Hamsterjagd"You ain't gonna need it!" (short YAGNI) is one of the most popular, and probably also most misunderstood and misused mantras of Extreme Programming. Again and again I see it used as an excuse to not improve a design "because it already works".
I guess the following has already been stated in hundreds of places on the web and elsewhere, in some form or another - on the other hand I also think it can't be said too often:
YAGNI applies to functionality, not design. All Agile approaches I know of are quite adamant about the fact that you need a clean, well decoupled, cohesive, duplication-free, expressive and extensively tested design from the beginning. One that is optimized for the currently implemented (and needed) functionality.