2
July 1998 97 Software Realities W hen we are asked to describe something, our natural impulse is to reach for an exhaustive defini- tion. If what we are asked to describe is a software concept—and if we are using a programming language— we will usually start writing a record, structure, or class definition, and we won’t come back until we have all the proper- ties in place. A bank account is the com- bination of the account holder’s name, a current balance amount, an account num- ber, an allowed minimum balance, and so on; a paragraph (in a text processing sys- tem) is the combination of a list of words, a default font, a justification rule, and so on. But we won’t feel comfortable until we have removed every single “and so on” and filled in all the details. How does object technology affect this? The first part of the answer is well known. It’s that the properties used in the description are no longer confined to attributes or data members, indicating what physically constitutes an object: Now they also include routines or meth- ods, indicating applicable operations. So we will not just have a record or struc- ture declaration, which in a Pascal-like language would read type ACCOUNT = record holder: PERSON; ... Other attribute declarations ... end but will obtain a true class by adding the routines, as in the following Eiffel form: class ACCOUNT feature holder: PERSON change_holder (new_holder: PERSON) is do .. end ... Other attribute and routine declarations end This example illustrates the principal and well-known difference, which also defines why a C++ class is not the same thing as a C structure. But there is another difference, no less important even if it is less obvious. The first form is explicit; the second is implicit. OPEN-CLOSED PRINCIPLE Implicitness here means that we do not claim to have listed all the properties— or care. In any class declaration there remains a possible “and so on.” We accept that the description may be incomplete, yet we can use it as it is. This is the open-closed principle, which in my opinion is one of the central innovations of object technology: the ability to use a software component as it is, while retaining the possibility of adding to it later through inheritance. Unlike the records or structures of other approaches, a class of object technology is both closed and open: closed because we can start using it for other compo- nents (its clients); open because we can at any time add new properties without invalidating its existing clients. The open-closed principle helps address a particularly pressing problem of software engineering: smooth evolu- tion. In the situation illustrated in Figure 1, we have a successful module A serving the needs of some clients. When new clients such as B1 appear with their own needs, non-OO approaches might force us either to change the original, thereby running the risk of invalidating all the existing clients (such as B and C), or to write a new module, causing duplication of software and probably duplication of bugs and future maintenance efforts. In the OO approach, we avoid this dilemma by writing A so that it is directly usable by B and other clients, yet is still open for adaptation through inheritance. A1, a descendant of A, does not dupli- cate the properties of A that are still applicable in the context of A1; it only defines what is different or new in that context. SAYING ENOUGH Applying the open-closed principle as a way of life in OO development means Tell Less, Say More: The Power of Implicitness Bertrand Meyer, EiffelSoft Object Technology Editor: Bertrand Meyer, EiffelSoft, ISE Bldg., 2 nd Fl., 270 Storke Rd., Goleta, CA 93117; voice (805) 685-6869; ot- [email protected] The open-closed principle is one of the central innovations of object technology. .

Tell less, say more: the power of implicitness

  • Upload
    b

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Tell less, say more: the power of implicitness

July 1998 97

Soft

war

e Re

aliti

es

When we are asked todescribe something, ournatural impulse is to reachfor an exhaustive defini-tion. If what we are asked

to describe is a software concept—and ifwe are using a programming language—we will usually start writing a record,structure, or class definition, and we won’tcome back until we have all the proper-ties in place. A bank account is the com-bination of the account holder’s name, acurrent balance amount, an account num-ber, an allowed minimum balance, and soon; a paragraph (in a text processing sys-tem) is the combination of a list of words,a default font, a justification rule, and soon. But we won’t feel comfortable untilwe have removed every single “and so on”and filled in all the details.

How does object technology affectthis? The first part of the answer is wellknown. It’s that the properties used in thedescription are no longer confined toattributes or data members, indicatingwhat physically constitutes an object:Now they also include routines or meth-ods, indicating applicable operations. Sowe will not just have a record or struc-ture declaration, which in a Pascal-likelanguage would read

type ACCOUNT =record

holder: PERSON;... Other attribute

declarations ...end

but will obtain a true class by adding theroutines, as in the following Eiffel form:

class ACCOUNT featureholder: PERSON

change_holder(new_holder: PERSON) is

do .. end

... Other attribute androutine declarationsend

This example illustrates the principal andwell-known difference, which alsodefines why a C++ class is not the samething as a C structure.

But there is another difference, no lessimportant even if it is less obvious. Thefirst form is explicit; the second isimplicit.

OPEN-CLOSED PRINCIPLEImplicitness here means that we do not

claim to have listed all the properties—or care. In any class declaration thereremains a possible “and so on.” Weaccept that the description may beincomplete, yet we can use it as it is.

This is the open-closed principle,which in my opinion is one of the centralinnovations of object technology: theability to use a software component as itis, while retaining the possibility ofadding to it later through inheritance.Unlike the records or structures of otherapproaches, a class of object technologyis both closed and open: closed becausewe can start using it for other compo-nents (its clients); open because we canat any time add new properties withoutinvalidating its existing clients.

The open-closed principle helpsaddress a particularly pressing problemof software engineering: smooth evolu-tion. In the situation illustrated in Figure1, we have a successful module A servingthe needs of some clients. When newclients such as B1 appear with their ownneeds, non-OO approaches might forceus either to change the original, therebyrunning the risk of invalidating all theexisting clients (such as B and C), or towrite a new module, causing duplicationof software and probably duplication ofbugs and future maintenance efforts.

In the OO approach, we avoid thisdilemma by writing A so that it is directlyusable by B and other clients, yet is stillopen for adaptation through inheritance.A1, a descendant of A, does not dupli-cate the properties of A that are stillapplicable in the context of A1; it onlydefines what is different or new in thatcontext.

SAYING ENOUGHApplying the open-closed principle as

a way of life in OO development means

Tell Less,Say More: The

Power ofImplicitness

Bertrand Meyer, EiffelSoft

Obje

ct T

echn

olog

y

Editor: Bertrand Meyer, EiffelSoft, ISEBldg., 2nd Fl., 270 Storke Rd., Goleta, CA93117; voice (805) 685-6869; [email protected]

The open-closed principle is one of thecentral innovations of

object technology.

.

Page 2: Tell less, say more: the power of implicitness

98 Computer

Object Technology

that the “and so on” of our lists of prop-erties is always there, even if not statedexplicitly. We do not need or want to beexhaustive.

If we later need to refine the conceptsof interest, we can do so without invali-dating the existing descriptions and—most importantly, from the viewpoint oflarge-scale and long-term software engi-neering—their clients. This does notmean, of course, that we should abuseinheritance and (like some object-ori-ented designers I have seen) introduce anew class each time we need a new fea-ture. A class should always define acoherent and significant abstraction, andif we are just adding a property that weinitially forgot, we should simply updatethe class definition. But for major adap-tations and extensions, we can afford toget the new and keep the old.

This absence of any claim to exhaus-tiveness gives a Zen-like quality to theprocess of OO modeling and design. Wedo not pretend that we try to say every-thing of interest, or even that we could.We say what we know of the objects ofinterest. We say what objects have; wedon’t pretend to have defined what theyare. As we learn more, we say more. Andat some stage we’ll just feel we haveenough—not all, just enough. At least forthe moment.

THE FINITE- FUNCTION MODELS

Looking at mathematical models canhelp you understand what’s going on. (Iknow that software people don’t “talkmath” in polite company. But there isreally no reason why in a scientific disci-pline we couldn’t summon the help ofmath to gain some insight into our prob-lem domain, especially when the mathinvolved is elementary.)

If we stick for simplicity to classes thatonly have attributes—the equivalent ofrecords—the most tempting model forsomething like

class ACCOUNT featureaccount_number: INTEGERcurrent_balance: REAL

end

is a Cartesian product: We can think of

this declaration as representing the setINTEGER × REAL—that is to say, theset of pairs <i, r>, where i is an INTEGERand r is a REAL. Although not wrong inany formal sense, this Cartesian productmodel creates a paradox: We cannotsubclass and subset at the same time!

Under no circumstance can A × B × Cbe mapped onto a subset of A × B; it’sactually the other way around. So if weare considering adding to ACCOUNT anew attribute, say address:STRING,we cannot consider the result a subsetof the original, even though that’s whatwe want since an “account with num-ber, balance, and address” is a specialcase of an “account with number andbalance.” Object technology allowsus—through polymorphism and dy-namic binding—to treat an instance ofthe latter as if it were an instance of theformer.

To remove the Cartesian product para-dox, it suffices to use a different model,one based on partial functions. Considera set T of tags that includes all tags ofinterest, such as account_number,current_balance, address, and aset V of values, which includes all valuesof interest, such as integers, reals, andstrings. Then we can consider a class suchas ACCOUNT as describing partial func-tions from tags to values with the prop-erty that every such function must bedefined for a finite set of values includingboth the tags account_number andcurrent_balance. Also, the value foraccount_number must be an integerand the value for current_balancemust be a real number.

AN EXAMPLEAn example is {<account_num-

ber, 9087123>, <current_bal-ance, 499.95>}, the finite functiondefined for exactly the two tags given,and describing a particular object—aparticular bank account with the twoattributes valued as shown (accountnumber 9087123 and current balance$499.95).

Then an instance of ACCOUNT_WITH_ADDRESS is a finite functiondefined for the tags account_num-ber, current_balance, and address.By its very construction, this is also an

instance of ACCOUNT as defined.In the Zen spirit of implicitness, we

never exactly specify the domains of ourfunctions (the precise set of tags forwhich they are defined); we simply listtags that these domains must include. Wedo not say that the domain of ACCOUNTmust be the set {account_number,current_balance}; we simply re-quire that it include the two tags given.

This is what makes it possible to con-sider descendant classes as subsets, eventhough they have more features. Like itssoftware counterparts, this mathemati-cal model is both open and closed.

U nder these mathematical observa-tions lies a very practical feature ofOO development, as distinctive as

anything that is routinely consideredpart of the definition of the approach—information hiding, classes, genericity,inheritance, polymorphism, dynamicbinding, contracts. It’s the constantrefusal to say more than what we strictlyneed to say.

The double refusal—refusal to close,refusal to assert completeness—requiressome intellectual audacity, but yields aproductive development process. In theend, what resolves the contradiction isthe release of the software. The releaseprocess—the process of closing what wasuntil now open—is the process of equat-ing each type with the Cartesian productof its properties. So when everything hasbeen said, the objects are indeed whatthey have. But only at the end. Untilthen, you always leave room for moreproperties.

Everything is open until officiallyclosed; and by telling less now you retainthe possibility of saying more later. ❖

AC B

A1 B1

Figure 1. Reconciling openness and closurethrough inheritance.

.