Specialization vs Generalization
Cognition or Artifact
Abstraction can be understood as a cognitive process or as its outcome. With the former acceptance, the mind deliberately ignores some features when processing actual perceptions; with the latter abstractions are symbolic artifacts meant to partially describe subsets of anonymous actual objects or phenomena.
Clearly that distinction may be critical when set along modeling processes.
Abstraction as Modeling Step
Whereas abstraction is likewise a catch-all concept, things are much more specific when the concept is put to use with generalization and specialization activities.
From a modeling perspective, specialization extends objects or activities while generalization factor out features or operations. As such, they meet different needs and are required in different modeling contexts:
- Specialization is needed when new features and behaviors are taken into account and therefore added to existing descriptions. As a consequence, specialization is not supposed to modify the semantics of existing artifacts.
- Generalization is justified when artifacts modelled separately are to be consolidated, which means that subsets of features and behaviors previously defined independently will be redefined with shared semantics. Hence, and contrary to specialization, generalization is meant to modify the semantics of existing artifacts.
In order to guarantee the traceability and transparency of models, whatever decision should be unambiguously qualified as specialization or generalization and, whenever possible, associated with specialization patterns.
Abstraction & Traceability
While extension and consolidation can be used all along the engineering process, their justification is obviously not the same for requirements and implementations. And that is to be clearly established when engineering processes are driven by models transformation.
Since specialization doesn’t affect the semantics of existing artifacts, changes in requirements can be directly mapped into their design counterparts. But that’s not the case with generalization because it affect upper levels of descriptions; as a consequence traceability has to be reconsidered for new as well as existing artifacts; for instance:
- Homing pigeons constitute an actual subset of pigeons. If new requirements introduce a functional subset for those used as carriers, its implementation can be designed without affecting existing classes, i.e traceability.
- Things are not so simple if carrier pigeons and human couriers are regrouped into a functional collection of carriers. In that case traceability between leaves will have to be redefined due to the insertion of a node with alternative designs (abstract class, interface, etc).
As a matter of fact, illustrated by this example, generalization should never be used at requirements level since it may affect the design of existing components without stating it explicitly.
Abstraction & Inheritance
Abstraction would be useless were it not for inheritance, but inheritance semantics often differ depending on programming languages. That difficulty may be overcome by applying inheritance selectively depending on their target, objects or aspects.
- Specialization is straightforward as subsets can be safely defined by combining aspects with sets of identified objects (a).
- Generalization is more problematic because it entails sorting out intrinsic features from aspects. For instance, given homing pigeons and couriers, one may assume intrinsic (and external) identities for pigeons and persons, or opt for a consolidated role supporting identification independently of any physical identities (b).
More generally, the distinction between objects and aspects open the way to a consolidated object oriented approach to business and system objects.
Abstraction & Model Driven Engineering
If specialization and generalization are well defined transformations of models, one may qualify how they should be used along the engineering process:
- Specialization can be introduced for requirements then directly mapped into design without explicit considerations to analysis models in-between.
- Generalization should not be introduced before analysis since it is meant to consolidate prior requirements. Generalization may also be used to consolidate designs.
Those principles have significant repercussions for development processes, especially for model driven ones.
Reverse engineering of legacy components is obviously first to be considered since it must be supported by direct traceability: upstream artifacts can only be retrieved along a one-to-one path from downstream implementations.
A more challenging issue pertains to the sequencing (or not) of development processes, more precisely to the debate between waterfall and agile schools of thought, with the former upholding the necessity of project milestones, and the later arguing against. If rigid dogmas are put aside, it is easy to see that decisions can only be made on a case-by-case basis: milestones are necessary when generalization is involved, iterations are safe whenever specialization is the tool of choice.
On a broader perspective, those issues can be consistently and comprehensively dealt with using a consolidated object oriented approach, applying selective inheritance for intrinsic features on one hand, contingent aspects on the other hand:
- If the continuity and consistency of contexts and systems are to be maintained, objects and processes are to be identified uniformly. Changes at that level may therefore entail consolidation across domains and organizational units.
- That’s not the case for roles and features whose change can be safely managed at project level.
With all models sharing an unified object oriented semantics, selective use of generalization and specialization can be adjusted to milestones and development iterations, from requirements to implementations.