A suite of eleven principles, conceived by people such as RobertCecilMartin
, etc. and compiled by RobertCecilMartin
There are six papers that describe all of these principles. They can be found in the resources section of http://www.objectmentor.com/
. The first four papers are named for the first four principles, the final papers cover the remaining two principles: "Granularity" and "Stability".
There are five principles of class design (aka SOLID):
There are three principles of package cohesion
There are three principles of package coupling
book claims that the single most important principle of OO design is BehavioralCompleteness
. And what would that be?
I would assert that this principal is covered by SRP, which as well as requiring a Class to exhibit a single responsibility implies that a responsibility should be entirely encapsulated by a single class. -- MartinSpamer
I believe this principle is valuable, at least so far as its name provides a meaningful key to thinking about design. Relative to the Principle of Essential Representation (PER) - proposed (below) as a single, basic principle for object-oriented design - the principle of BehavioralCompleteness
covers that a representation (e.g. a type) should include all
its essential representations (e.g. behavior characteristics, or method and events). However, it does not explicitly cover that a representation also should include only
essential representations. We could say, to elaborate the principle of BehavioralCompleteness
, that a representation should not "over-behave" or be "over-complete". This would beg the question of what is "over", and how we can tell. The concept of an "essential representation"; the interpretation of 'essential' as necessary and original using a simple, intuitive version of "possible world semantics"; and the application of a "method of variation" to explore possible worlds and distinguish essential representations, does cover this: including inessential
behaviors - ones that do not vary, across some possible worlds, only with the identity of their types - is "over-behaving" or being "over-complete".
-- Carl R. Castro
Are there other principles of object-oriented design than those listed by RobertCecilMartin
Yes! In particular see the list of (often conflicting) DefinitionsForOo
, including the links (in particular the stuff on paulgraham.com that is linked to was a bit too long to paraphrase on c2.com). I think RobertCecilMartin
is interesting, and says worthwhile things about software, but truthfully he really annoys me by redefining words. He has an idiosyncratic definition for "OO" in particular that no one in the world except his followers share, as mentioned on the cited page. His list on PrinciplesOfObjectOrientedDesign
, on the other hand, is an excellent list, but again, is about software in general, absolutely not about OO in particular; most of it applies perfectly well to old style structured programming in procedural languages. Which reminds me, see the much-neglected yet not obsolete CouplingAndCohesion
. -- dm
A Single Basic Principle for Object-Oriented Design
I believe there is really just a single basic principle of object-orientation and object-oriented design (OOD), which I would like to call "The Principle of Essential Representation" (PER).
Other principles are corollaries, interpretations or applications of this principle; so are the relational normal forms.
The Principle of Essential Representation (PER)
Simply put, this principle states that:
Similar Principles, and Essence as Relative in Representations
- a definition or representation (in a design or implementation language) should contain all and only "essential" definitions or representations (this generally means, in the definition of a type, the definitions of its state & behavior characteristics, or methods, properties and events)
- all "inessential" definitions or representations should be contained in other, related representations
So stated, the PER seems quite similar to Meilir Page-Jones' principle of "connaissance" - that characteristics which are "born together" should "go together" in a representation. However, this rough statement of that principle might suggest that connaissance:
- is a specific relationship ("togetherness") between characteristics forming a representation...
- ...and not a condition (its being "essential") on the basic relationship (the "has" relationship, etc.) between a representation (e.g. a type) and any of its contained or owned representations (e.g. the type's characteristics), as is the PER
So what is important to note here is that the "essentialness" of a representation is relative to an owning or containing representation -- e.g. a characteristic is essential to
(I would like to acknowledge Mr. Page-Jones, however, not only for all his excellent writings but as being the only person - at least whom I have been able to discover - who has even proposed a single basic principle of object-orientation.)
Meaning of the Term 'Essential' and Possible World Semantics
This principle of course requires an interpretation of 'essential' or of 'essence' as applied to characteristics.
There are several aspects to such an interpretation, but basically:
- an essential characteristic is "necessary" - or applicable in "all possible worlds" - or in software worlds, in all possible applications, configurations, implementations, etc. -- i.e. with any possible surrounding representations
- an essential characteristic is non-derivative or "original" - or is applied (defined) only at the highest level (at which it is necessary) in a hierarchy
This interpretation of 'necessary' is actually a simple, intuitive version of Saul Kripke's "possible world" semantics for modal logic.
Applying the Principle by a "Method of Variation", and the Example of the Derivation of MVC
On this interpretation, necessary characteristics can be discovered by applying a "method of variation" to representations - and to the possible applications, configurations, implementations, surrounding representations, etc. - in which they might occur, in something like OOD "thought-experiments".
A prime example of applying this "method of variation" is the derivation of the famous MVC (Model-View-Controller) pattern (which is a kind of basic pattern whose tripartite scheme can be extended in some way to solve almost every OO design problem):
Tripartite Schemes as Exemplifying the Principle in General
- (step 1a or b) By varying possible styles or types (or even the existence) of view for a model object, we can see that view characteristics are not essential to model representations.
- (step 1b or a) By varying possible types of model for a view, we can see that model characteristics are not essential to view representations.
- (result of step 1) >> This gives us separately-encapsulated model and view - at least a bi-partite scheme, which achieves independence of implementation (but not of declaration) between model and view.
- (step 2) By considering possible variation in declarations of methods by which model and view would be related, we can see that the relationship between model and view should be separately encapsulated in a controller.
- (result of step 2) >> This gives us a tripartite scheme that achieves a maximal independence of definition (both declaration and implementation) between model and view. With this maximal independence of definition comes maximal reusability - and also maximal clarity or exposure of design - the basic goals of object-orientation. Also, the controller sets a boundary to the propagation of change in an application; unless the semantics of the application (i.e. the information passed) change, the propagation of change between model and view stops at controller. This gives maximal maintenability.
A similar derivation applying the method of variation can give us good designs for object-relational mapping, considering the relationship between model objects (the object-level "view") and objects in a relational layer (the data-level "model").
In general, tripartite schemes (with a third partition as an actual type or as virtual, in an interface) are the result of applying the PER. Tripartite schemes generally capture the "appearance" of information (at some level of an application), its "reality" (at another level), and the relationship between them - with "appearance"/"reality" providing a basic way of thinking about transformations of information and interactions with it. This is why MVC can seem so powerful as a basic, extensible pattern and why it has become so popular as an effective one. (Check out the webpage of Trygve Reenskaug, its inventor: http://heim.ifi.uio.no/~trygver/
The Importance of a Single Basic Principle
Having a single basic principle of object-orientation is important, because:
Details of Applying the Method of Variation, and Similarities in Applying the Relational Normal Forms
- having many principles begs the question, "What is it about these principles taken together that makes them principles of object-orientation?" or "What about object-orientation makes it explicable or capturable by these principles taken together?"
- patterns alone aren't enough - we need to be able to say what makes a pattern a good pattern (vs. a bad or an anti-pattern), beyond just saying that the pattern "works" (this also dispels specious anti-principle influences culled from so-called "ordinary language" philosophy latent in Christoper Alexander's work and its applications to OO)
- a single basic principle helps to explain how it is that we can understand OO and OOD - how we can suddenly "get" (grok) object-orientation, and what it is that we "get" when we do get it; how we can and naturally do think using representational concepts such as type, method, property, etc.
- a single basic principle is easier to remember than many principles! ;)
There are actually some subtleties or details to the application of the "method of variation" to distinguish essential vs. inessential representations. These subtleties or details make this method similar to the method of distinguishing invariant data in applying the relational normal forms. Recall that an essential characteristic is necessary (as well as original), and that a necessary characteristic applies in all possible worlds, despite variation in application, configuration, implementation - in short, despite any variation in surrounding representations. In object-oriented applications, representations or definitions may indeed vary - polymorphism is a quite intentional and notable example of such variation. But in this case, the variation in implementation for polymorphism corresponds to a variation in subtype. So we can consider the identity of a type in the application of the method of variation to be like the primary key of a row in the application of the relational normal forms: an inessential characteristic is one that varies independently of the identity of its type. Such a characteristic should instead be represented in another, related type. Similarly, for example, the name of an employee's department manager should be represented in a department table, not in the employee table, where it varies with something other than the employee's primary key - and these tables should be related by a foreign key.
The consideration of relationship when inessential characteristics are "moved" to other types in the design of object-oriented applications is a bit different than the introduction of foreign keys in relational modeling; I would hazard to say it is a bit more thorough-going than the conventions of relational design, which do not explicitly consider partitioning (perhaps just because there are not the two explicit aspects of definition - declaration and implementation - in relational models).
Consider the example of the MVC pattern: recognizing that the implementation
of view methods can vary independently of model types, we separately encapsulate model and view, achieving at least a bi-partite scheme.
A designer might be tempted to stick with a bi-partite scheme, providing a "standard interface" in her architecture for passing values from the view directly to the model - perhaps a name/value pair object that is passed to a save
method of the model object whenever the clickOkay
event of the view object occurs.
However, if the application varies so that the save
method of the model object no longer exists, or is no longer named "save", or no longer takes an argument of the same type for passing values (even if it is a name/value pair object of another type) - that is, if the declaration
of the model object varies, then the event code of the view object must vary, even though there has been no variation in the type of the view object. In this design, the implementation (a definition or representation) of the view object varies independently of its type, and so is not essential. Another design, without the assumptions of such a "standard interface", is required to eliminate this variation and so to make the definition the event an essential one. For this, the value information from the view object is passed to an object that encapsulates (represents) the relationship
between model and view; such an object (i.e. a controller) can perform whatever translation of this information may be needed for, and invoke the appropriate method of, the model object. If there are changes to the save
method of the model object - its name, its argument types, etc. - these changes propagate only as far as the controller, and not to the view (unless the semantics
of the application change, and more information is needed).
I hope these last few paragraphs firm up and clarify the PER, the concept of "essential representation" as necessary and original, and the application of these by a "method of variation". Really, this principle and its concepts are innate to the ways good designers basically reason about their designs, and to good basic patterns such as MVC. I believe the principle has not yet been articulate due to the combined requirements of modal concepts (such as "necessity"); general but intuitive ways of applying them (such as "possible world semantics"); and interpretations of these for the constructs of object-orientation (the "method of variation" as specifically described above).
Thanks for reading,
-- Carl R. Castro
Could you elaborate on "go together"? I tend to view "go together" as circumstantial (EverythingIsRelative), and thus I am a RelationalWeenie who wants "togetherness" to be ad-hoc for different viewpoints or situations involving the same info. Also, it might be interesting to see how MVC allegedly naturally comes about by your principles in a step-by-step fashion. Perhaps this should be moved to GroupRelatedInformation. -- top
Thank you for these questions.
So far as "go together": the use of this phrase is to summarize Page-Jones; really, he should be the canonical reference on its meaning. I would say that it means "are characteristics of the same representation" - which of course begs the question of relativity which you posed. So far as relativity or circumstantialness is concerned, I think that there is a distinction between a "natural representation" and an "artifactual representation"; the latter kind of representation being what is called a "role" in OO. Many apparently natural representations - e.g. "customer" - are actually artifactual: a customer as a person does not necessarily have an email address, but our company may require an email address for a person as a customer. This involves some kind of stipulative definition, or specification of a "role" - an artifact of a way of doing business, etc. (Trygve Reenskaug, of MVC fame, has done lots of work on roles and collaborations, too: http://heim.ifi.uio.no/~trygver/themes/roles/roles-index.html
) Note that natural vs. artifactual has to do with the source of the necessity - but not with its mode or nature; the same possible world semantics can apply. Becoming philosophical, I suppose one could say that this does mean that necessity is relative (to role and its stipulative definition or specification); Kripke actually covered such issues in his semantics for modal logic using "accessibility" relations between possible worlds. I would say that ultimately, everything is relative, but that relatively (given we are in the relative world), there can be a single basic principle, as long as we don't seek after a kind of absolute meaning for its terms and phrases, one that can completely and independently determine its application. (For more on this, read Kripke's discussion of Wittgenstein's supposed argument RE "following a rule" in the Philosophical Investigations; I feel that Kripke did not get to the bottom of Wittgenstein's approach, but did provide many useful insights on it.) I tried to review and comment on EverythingIsRelative
, but I got lost in the reference to SoftwareHippy
So far as the steps of the derivation of MVC - I've recently edited and elaborated on these for clarity above, but in other words, they are roughly as follows.
- Generally, apply the "method of variation" to the relationship between model and view representations (characteristics and types):
- Consider whatever representation to which model characteristics naturally belong.
- Consider whether view characteristics are always characteristics of that representation. (Do this by varying the possible views of the model, and considering existence of a view altogether. Also do this by considering variation in both the implementation & the declaration of the view characteristics - can these both vary for the "same" model?)
- Conclude that view characteristics can vary in existence and in both implementation and declaration for the same model - i.e. are not necessary or essential to the model - and so should be separately represented from model characteristics. (This gives just two partitions - model & view.)
- Consider whether the relationship between model & view can vary - whether the communication or messaging between model & view can vary. (Do this by varying the possible interfaces of the view, interfaces that must be used by the model on this relationship - this is variation of declaration, not just implementation.)
- Conclude that the relationship (i.e. the interfaces used) can vary - i.e. is not necessary or essential to either model or view - and so should be separately represented from either model or view. This gives 3 partitions - MVC, voila!
So far as moving to GroupRelatedInformation
- I believe this would obscure a role as a basic principle, and also would emphasize a relationship between characteristics themselves, which is not always the basis for their inclusion together in a representation, which is a point of this principle.
-- To discuss this further offline - carlRcastro@yahoo.com.
, CategoryObjectOrientation CategoryDesign