I had a good question from an architect the other day. He was looking at one of my models, where I had created an abstraction and then modeled some of the concrete entities under it. He didn’t believe that the abstraction was necessary.
He mentioned that it is possible to create abstractions from nearly any pair of objects in the world. An infinite variety of abstractions are possible. Therefore, we need to create abstractions only when they are useful. Otherwise, the abstraction, and subsequent inheritance, simple add complexity to the solution.
Of course, I defended my design like a champ, but it did make me think: what is the rule of thumb? What is the lithmus test for whether an abstraction is needed or not?
The answer that I’ve settled up, after thinking about it, is that an abstraction is primarily useful in two cases: 1) to create a list of items that may change, or 2) to seperate two different lists of items, especially if the membership in one or both lists may change during the lifetime of the system.
In other words, if you have a system that cares only about apples, and provides a list of the attributes of an apple, and the list of attributes changes over time, then you don’t need an abstraction between the apple and the list. The list is simply attached to the apple. On the other hand, if you want to change the apple to a list of different kinds of fruit, then you now have two lists (fruit and attributes) and it makes sense to place an abstraction between them (good choice may be the Bridge pattern).
Another abstraction is the list of business capabilities provided by the MSBA capability hierarchy. The strategies of a company change, and the business processes change. You need a stable abstraction between them (the business capability hierarchy) to allow you to convert strategy to changes in business process in a rational and simple manner.
PingBack from http://msdnrss.thecoderblogs.com/2007/08/08/when-do-you-need-an-abstraction/
PingBack from http://msdnrss.thecoderblogs.com/2007/08/08/when-do-you-need-an-abstraction/
PingBack from http://msdnrss.thecoderblogs.com/2007/08/08/when-do-you-need-an-abstraction/
I think a rule of thumb for the need of abstraction is whether you want to support an n:m relationship (yes, abstraction) or you only want to support a 1:m or even a 1:1 relationship (no abstraction needed). Mind that a 1:1 relationship is a special case of a 1:m relationship and a 1:m relationship is a special case of an n:m relationship. You must be visionary in recognizing that a current 1:m relationship might in future appear to be an n:m relationship. So a good practice to create flexible systems is to use abstractions whenever possible.
Or am I missing something?
Jack
Hi Jack,
I think we are saying the same thing. The notation "n:m" implies two lists (list ‘n’ and list ‘m’) that need to vary independently.
In a sense 1:m still requires an abstraction to hold the list ‘m’ (even a simple array is, effectively, an abstraction).
— N
I think you missed an important one. When you want to test the collaborators of that thing in isolation by providing some sort of test double (mock, fake, stub, proxy, what-have-you).
I can see two primary uses of abstraction (please let me know if you can think about something else which is not derived from these):
1. Reduce Complexity:
Goal here is to manage complexity by reducing the amount of information that must be considered at one time. Approach is to separate information important to the problem at hand from that which is not.
2. Model the problem domain. Goal is to leverage domain knowledge to simplify understanding, creating, checking designs. That’s essentially creating an abstract data type.
Abstraction always defines a one-to-many relationship: abstraction is one, instances it represents is many. If you can’t think about more than one instance, then you didn’t really create an abstraction.
Abstraction also has direct application for design for change when we want to change the module implementation without changing its interface. Abstraction in this case is the interface of the module and specific instances are different implementation of the module.
Does it make sense?
I think what you guys are hinting at is the "stability" of abstractions. That’s one reason to use them. The more abstract an item is, the more stable it is (think interfaces vs abstract classes with default implementations). Putting an abstraction in the middle of an interaction brings stability.
The interaction could be between two implementations (classes), two components, etc. They could include an interface, an abstract class, an interface assembly, and probably a bunch of other things I can’t think of off the top of my head. 😉