Archive

Posts Tagged ‘object oriented design’

Irritated

October 13, 2012 Leave a comment

Unsurprisingly, one of BD00’s posts irritated a reader who stumbled upon it. For some strange reason, BD00’s scribblings have that effect on some people. In the irritating post, “The Old Is New Again“, BD00 referred to Data and Control Flow diagrams as “old and obsolete“. In caustic BD00 fashion, the reader commented:

Use Cases and Activity Diagrams, in contrast (to the Data Flow diagram), offer little guidance in effective partitioning. They rely upon the age old “sledge hammer” approach to partitioning” (ie, just break-er-up any way you can). Sledge hammer partitioning is what cave men used to partition entities. So in a critical sense, DFD’s are new and hip, while Use Cases and Activity Diagrams are based upon logic that is older than dirt.

BD00 likes all visual modeling tools – including the DFD hatched during the heyday of structured analysis. BD00 only meant “old and obsolete” in the sense that DFDs pre-dated the arrival of the UML and the object-oriented approach to system analysis and design. However, BD00 did feel the need to correct the reader’s misunderstanding of the features and capabilities that UML Activity Diagrams offer up to analysts/designers.

Both the DFD and UML activity diagram pair below equivalently capture an analyst’s partitioning design decision (where DFD Process X == Activity Diagram Action X). Via “swimlanes“, the lower activity diagram makes the result of a second design decision visible: the conscious allocation of the Actions to the higher level Objects that will perform them during system operation. So, how are UML activity diagrams inferior to DFDs in supporting partitioning? A rich palette of other symbols (forks, joins, decisions, merges, control flows, signals) are also available to analysts (if needed) for capturing design decisions and exposing them for scrutiny.

DFDs and UML diagrams are just tools – job performance aids. Learning how to use them, and learning how to use them effectively, are two separate challenges. Design “guidance” for system partitioning, leveling, balancing, etc, has to come from somewhere else. From a mentor? From personal experience learning how to design systems over time? From divine intervention?

Graphics, Text, And Source Code

December 29, 2011 3 comments

On the left, we have words of wisdom from Grady Booch and friends. On the right, we have sage advice hatched from the “gang of four“. So, who’s right?

Why, both groups are “right“. If all you care about is “recording the design in source code“, then you’re “wrong“…

If you’re a software “anything” (e.g. architect, engineer, lead, manager, developer, programmer, analyst) and you haven’t read these two classics, then either read them or contemplate seeking out a new career.

But wait! All may not be lost. If you think object orientation is obsolete and functional programming is the way of the future, then forget (almost) everything that was presented in this post.

Which One, And When?

April 23, 2011 Leave a comment

Option A and Option B in the UML figure below show two different ways of presenting the same 3-function interface to “other” code users. Under which conditions would you choose one design over the other?

Because I prefer simplicity over complexity and local dependency over distant dependency, I’d prefer option B over option A if I was reasonably sure that classes A and B wouldn’t be useful in another inheritance tree or useful as leaf classes. Even if I chose wrongly, because all the functionality is encapsulated within one class in option B, it wouldn’t be a huge risk for a user to extract out B or C class sub-functionality from D and customize it for his/her use by placing it in his/her own separate E class. In this case, no other existing clients of class D would be affected, but the trade off is the introduction of duplicate code into the code base. If I chose the option A inheritance tree, this wouldn’t be the case. In option A, if a user was allowed to directly change A and/or B in-situ, then the duplicate code “wart” wouldn’t manifest, but the risk of breaking the existing code of other users of the A, B, and/or C classes would be high compared to the alternative. Do you see any holes in this decision logic?

Improper Inheritance

January 5, 2011 Leave a comment

Much like Improper Inheritance (II) can wreck family relationships, rampant II can also destroy a project after large and precious investments in time, money, and people have been committed. Before you know it, BAM! All of a sudden, you’ve noticed that you’re in BBoM city; not knowing how you got there and not knowing how to get the hell out of the indecipherable megalopolis.

Here’s what the “C++ FAQ” writers have to say on the II matter:

Here’s what Stephen Dewhurst says in “C++ Gotchas” number 92:

Use of public inheritance primarily for the purpose of reusing base class implementations in derived classes often results in unnatural, unmaintainable, and, ultimately, more inefficient designs.

Herb Sutter and Andrei Alexandrescu‘s chapter number 34 in “C++ Coding Standards: 101 Rules, Guidelines, and Best Practices” is titled “Prefer composition to inheritance“. Here’s a snippet from them:

Avoid inheritance taxes: Inheritance is the second-tightest coupling relationship in C++, second only to friendship. Inheritance is often overused, even by experienced developers. A sound rule of software engineering is to minimize coupling: If a relationship can be expressed in more than one way, use the weakest relationship that’s practical.

On page 19 in Design Patterns, the GoF state:

“Favoring object composition over class inheritance helps you keep each class encapsulated and focused on one task. Your classes and class hierarchies will remain small and will be less likely to grow into unmanageable monsters.”

Let’s explore this malarial scourge a little closer with a couple of dorky bulldozer00 design and code examples.

The UML class diagram pair below shows two ways of designing a message. It’s obvious that a message is composed of a header and payload (and maybe a trailer), no? Thus, you would think that the “has a” model on the left is a better mapping of a message structure in the (so-called) real world into the OO world than the multi “Is a” model on the right.

I don’t know about you, but I’ve seen many mini and maxi designs like this implemented in code during my long and undistinguished career. I’ve prolly unconsciously, or consciously but guiltily, hatched a few mini messes like this too.

For our second, more concrete example, let’s look at the mixed design and code example below. Since the classes and member functions are so generic, it’s hard to decide which one is “better”, no?

By looking at the test driver below, hopefully the “prefer composition to inheritance” heuristic should become apparent. The inheritance approach breaks encapsulation and exposes a “fatter” interface to client code, which in this case is the main() function. Fatter interfaces are more likely to be unknowingly abused by your code “users” than thinner interfaces – especially when specific call sequencing is required. With the composition approach, you can control how much wider the external interface is – by delegation. In this example, our designer has elected to expose only one of the two additional interface functions provided by the Base class – the ifaceFunc1() function.

Like all heuristics in programming and other technical fields of endeavor, there are always exceptions to the “prefer composition to inheritance” rule. This explains why you’ll see the word “prefer” in virtually all descriptions of heuristics. Even if you don’t see it, try to “think” it. An equivalent heuristic, “prefer acceptance to militancy“, perhaps should also hold true in the world of personal opinions, no?

%d bloggers like this: