"Smalltalk is the one language I know which expresses 'design' directly"
is an interesting statement, but I'm at a loss as to what precisely it means for a language to be ExpressingDesignDirectly
, such that Smalltalk and maybe LISP or APL do so but (one assumes) C++, Java, or other candidates do not. -- JimPerry
Guilty as charged, so I'll take the first stab at why I said that. To me, an object-oriented software 'design' is the partitioning of the system into modules, with their interfaces and communications. I suspect a few people may flatly disagree with this, and others will find it too narrow. But for me, that exactly is the topic. The partitioning drives both the human teaming and the "trajectory of change" for future modifications.
Programming languages have several dimensions of expression, they contain different sublanguages, if you will. There are sublanguages to express typing issues, behavior issues, parallelism and concurrency issues, module boundary issues, and so on (I spent a small chunk of time in IBM Research playing with creating languages by mixing, matching, and inventing these sublanguages, until I decided that there wasn't great gain in it - but it was useful in terms of seeing how independent all these sublanguages are).
One can say that 'design' is all of these dimensions. Since for me, the 'design of the system' is in the partitioning of the system, I am interested in a language that reduces the other issues. C++ has a very large component to express intention about typing; Java has large component concerned with package handling and location. Smalltalk is almost strictly behavioral. The language pretty much can't express anything that is not of "do this" flavor - even the class declaration is an instruction to an existing class to "make a subclass out of this". Method declarations are about the only things that are not straight behavior.
This means that when I look at a Smalltalk program, what is there, with the least distraction and least overhead, is the "design" (as I have described it) of the system - the partitioning and the communication. And it runs. Hence I get around to saying that Smalltalk expresses design directly (or the most directly of the languages I know).
LISP is also strictly behavioral, but I don't get the component boundaries clearly, ditto APL2, although both can be used to create "design" in the sense I used.
p.s. I hadn't been following TheSourceCodeIsTheDesign
, and just read it, and realize now that I chose here a particular aspect of 'design' as discussed there. Nonetheless, I think you will find that this 'design' here addresses the thing that Ralph and Ward were discussing there - they were discussing not understanding HotDraw
from simply reading the Smalltalk (!) code. I am not concerned here with someone learning the design from reading the code (as I put into PeteMcBreen
's mouth in GeneratingCppFromSmalltalk
, the best way to transfer the design into implementation is to transfer the heads that know the design). I am interesting in the design creators understanding the consequences of their design decisions - and for me that is the partitioning issue.
OK, you really mean that it expresses what you consider the essence of the design minimally, without what to you is overhead.
Most directly to your taste
Fair enough. To my taste, I'd rather see the type information present in more typed languages (C++ and many others). My bias is to consider that part of the design (even if the implementation language is not enforcing it as such, it's part of the design: I expect a WidgetController?
object here, not a UserPreference
). As indicated in GeneratingCppFromSmalltalk
you're talking about extending Smalltalk (via comment conventions) to include such design annotations, so I don't think I'm too far off saying they're a sensible part of the design in the first place. -- JimPerry
To clarify I'm not particularly claiming any language I know of expresses design directly, just questioning the assertion that a particular one does so better than others. -- JimPerry
In my experience, objects express design better than other forms of software modularity, e.g. function and package.
Also in my experience, Smalltalk expresses intent better than most languages, due to the absence of language clutter such as typing, casting, braces, and lots of irritating silly parentheses.
Perhaps these two dimensions working together contribute to the effect Alistair mentions. If this is true, there might be more to what he says than mere personal taste. How might this be tested? -- RonJeffries
Objects express object designs well, so let's stick with OO languages.
What's clutter or irritating to one person is useful structure to the next. A good development environment helps. (LISP without a good editor can be annoying, but what's Smalltalk without its environment?)
If you find Smalltalk expressive then by all means stick to it. I find it no less readable than many other programming languages but certainly no more so. A matter of taste and experience, no doubt.
If Smalltalk objectively
is more capable of ExpressingDesignDirectly
than the alternatives, then it should no doubt win out as a design notation in the long run ;-). -- JimPerry
I think you forgot the smiley face :-) at the end of that last sentence, to indicate tongue-in-cheek, since we should know by now there is no particular correlation between 'best' and 'winner'. :-) -- AlistairCockburn
Half-smiley, perhaps. But isn't the trend toward UML and CPL and otherwise assimilating the best practices into one Utopian whole? (No emoticon can adequately punctuate that
.) -- JimPerry
Only if one subscribes to the theory that the best technology wins - I do not so subscribe. -- rj
More seriously, people sometimes think a "considered opinion" is a "religious assertion". I am offering the above as a considered opinion. I am on record with the considered opinion that C++ made some mistakes regarding typing and programmability, but that is not in play here. I am also on record with frustrations with not being able to express certain things I care about with Smalltalk (indeed, any imperative language). I have also programmed in assembler, Algol, Pascal, PL/I, C, Prolog and Java, and my comments here apply equally to those languages, because they are concerned with other matters than the key design issue of partitioning.
Type information, "what I anticipate to be needed in a parameter so the system does not misbehave", is indeed part of the design. However, it is at the, say, 3rd or 4th decimal point of precision in the design, whereas the subsystem or class-category or UML-package partitioning is at the 1st decimal place, and the class/object partitioning is at the 2nd decimal place. Having the partitioning wrong, the type information isn't going to save us. Teams get assigned on the basis of the partitioning, so it has long-term consequences. "Which teams get drawn in to make a change" is a consequence of the partitioning. Partitioning, sadly, gets evaluated at the end of the story, when all the subsystems are finally debugged and integrated - far too late to take advantage of the feedback that is finally available.
is about executable descriptions of partitioning. Smalltalk is the one language I know which addresses that concern directly. Interesting you bring up readability. I hadn't considered the impact of readability, in the LiterateProgramming
sense. I agree Smalltalk is not especially readable - it just gets the other clutter out of the way. Probably that is the aspect of readability I care about here.
My annoyance with Smalltalk and the other OO languages I know is that I can't express declarative things that are important to the design, such as the design patterns used. E.g., I really would want to say, "I'm going to use MVC here, where the model class is this, the view class is this, the controller class is this, and here are the options on MVC I need this time." I.e., cross-class rules. What the OO languages give me is one class here, which coincidentally just happens to be a view class with the correct protocol to work with this other class, which just happens to be a model protocol with, remarkably, just the right protocol, etc. However, for a good while in the project, I can work without that improved expression... and I also don't know any language that will let me express it.
Picking up on Ron's question, how would we test my assertions about design? -- AlistairCockburn
My question above is "how might this be tested". I suppose another question might be whether it is worth while to test it. Quite likely, those who use language to express design use whatever language they know best, not whatever language IS best.
However, C3's practice, supported by results, is to use [Smalltalk] language as the only
permanent record of the design. We often
the design in CRC, but we only record
it in code. Works for us ... and as a qualified practitioner in other languages, I'd be less sanguine about trying to do the same thing in most of the others. But is this material? Maybe not.
Speaking to the expression of type, in well-written Smalltalk code the object names (as well as the class names) directly express type. Instead of something like
we would see something like
person setName: 'Jeffries'
so the type is right there in your face. If the code were not written with the type carried in the variables, I too would want it in the header.
Of course, this is a StrawMan argument. Both choices were BadVariableNames. What's a p? Which person? Why didn't you name it something like CoachPerson?? Moreover, why couldn't you go "Person person;"? Or "p := new Person."? -- SunirShah
If type information is actually that important, then perhaps my starting assertion is wrong... I continue to think my starting assertion is right :-)), but Wiki-ites have shown me the errors of my ways, before. -- AlistairCockburn
And I agree with you ... that means we are almost certainly wrong. -- RonJeffries
I just have to add here that if the intention truly is to express a design that will be implemented in C++, then typing really does bump up a few decimal places. Particularly if you want to do detailed design in Smalltalk.
Many people don't see why C++ programmers make a big deal over the LiskovSubstitutionPrinciple
. It is easy enough to make subclasses which do not substitute for their superclasses, provided no one ever does the substitution. But, in strongly typed languages, the code becomes littered with formal argument types which make sure that the only
things that you can substitute for objects of a class are objects of subclasses. That is the only way we get polymorphism for method parameters. Smalltalk drips with polymorphism, so it may be easier to design with roles in mind rather than actual classes and end up with something that requires a lot of skull sweat to translate to C++.
To me, if typing is part of the target language, then committing to a detailed design gleaned from Smalltalk without the diligence of someone who lives and breaths strong typing rules would incur unnecessary risk. But, I frankly admit that I do not know this to be the case, and I'm not sure how often people take advantage of non-subclass polymorphism in Smalltalk. Maybe someone can enlighten me. Moreover, maybe there are some good examples of projects ported from Smalltalk to typed languages which give some clues. I just remember that it seemed to take the industry, as a whole, a while to "get" LSP and its ramifications and it would be horrible to see it sneak up on unsuspecting projects again.
says: "That's just my opinion, I could be wrong."
I'm with Michael, type information is certainly important in many languages, and I think more that Alistair suggests in general, but that's not for here. I still maintain that if Smalltalk requires additional annotations to express information needed by a C++ design (at a minimum) then it's not ExpressingDesignDirectly
more than any other language.
Ron brought up readability. I'm more concerned with interfaces, not implementations; how a method does what it does is (to me) quite a few decimals down the tree (but if you look at interfaces, I think type bumps up higher).
It may be a benefit in the design process to be able to execute an incomplete design (not all the t's dotted nor i's crossed nor types specified), but I don't buy that as ExpressingDesignDirectly
. If types are (and they are) part of the design, they need to be expressed. -- JimPerry
Good. You have shifted my views. I had indeed been thinking that the modularization and behavior of the modules represented "the design." I now see more aspects to "the design" than I had before, and understand that you and some others like to see interface typing early in the design process. I still think that getting the behavior of the modules straightened out is more significant (1st and 2nd decimal place of precision) than getting the types (3rd and 4th decimal places). Hence I would prefer executable Smalltalk used to examine the design or architecture than non-executable IDL. I wonder whether you really believe the typing information comes before the behavior partitioning. I doubt it, and the reference to "how a method does what it does" dodges the question.
Now I understand why you wouldn't think of Smalltalk as supporting ExpressingDesignDirectly
. Now I now think of Smalltalk as expressing the first couple of places of precision directly, but not the other bits of precision. And perhaps I understand why I never nominated Prolog for any of this - it captures neither module partitioning nor typing. -- AlistairCockburn
That makes sense to me. To me, especially in the GeneratingCppFromSmalltalk
context, something that expresses design directly would mean something which could act as a specification (if not direct translation source) for an implementation in any reasonable target language. That's what the lines-clouds-and-boxes methodologists are pushing, in a sense, but an executable reference implementation-as-specification in a simple common language has some appeal.
I think I agree in broad terms on design levels. Clearly (it seems to me) you have to pick your modules/classes and define their high-level interactions (select CRC cards, draw UML boxes, whatever) before you specify the specific methods within those classes, and you want to do that before you decide what the specific type signature of each method is (or at least you decide you need a method before deciding its
signature). So I wouldn't say (and haven't said) that you'd design types before
classes (behavior partitioning).
But it seems to me that I'd want to get at least to the point of method signatures before attempting any implementation. Sure, there are environments where one can enter incomplete components into a computer as you design, but I'd just as soon use cards or whiteboards. So to this point, before implementing anything, you've designed classes, methods, and method/argument types, if not method implementations. -- JimPerry
This is good if you favor DesignBeforeCoding.
I'm guessing you haven't used Smalltalk much, Jim. We XP people determine classes and method signatures by actually writing the code, in an evolutionary fashion. Having done systems both ways, with and without large amounts of upfront design, we've found that we go faster by "designing" directly in Smalltalk. And as we have reported elsewhere, we have produced a flexible design, clear code, predictable delivery dates, high reliability, and very happy customers. We do not recommend the approach lightly. -- RonJeffries
Thanks, Ron, this is information I didn't have before (no, I haven't used Smalltalk much, as I've tried to make clear). Your (collective) descriptions elsewhere (use of CRC) led me to think at least the early phase of your process was some flavor of DesignBeforeCoding
(which to me is like saying LookBeforeLeap?
). And just perhaps you're conflating XP with Smalltalk, as I'm fairly confident there are Smalltalk advocates around who also advocate DesignBeforeCoding
(which I would distinguish from BigDesignUpFront
There are clearly multiple uses of 'design' floating around here, but surely if one doesn't DesignBeforeCoding
, i.e. if TheSourceCodeIsTheDesign
at all phases, then there is a real question as to whether there exists
such a thing as a "design notation". In such a world view, the implementation language and the design notation are one and the same (as reflected in the comments below). That being so, the question underlying this page reverts, in essence, to "why X is my favorite programming language". -- JimPerry
To date, man has not discovered a perfect design notation. This perfect notation would be one which, in one package, embodies every aspect of the program from function to performance, makes every tradeoff clear, cannot be mis-implemented, and so on.
Let's consider two possible notations, Smalltalk near one boundary, and the reader's choice of design notation (TRML) near another. One difference between these points is rapidity of feedback between design and implementation. Since the Smalltalk is
an implementation, the feedback is pretty hard to beat. Get a design idea, try it, assess how it really works rather than how we think it will work.
There may be other critical differences:
Speed of change:
Which alternative makes it easier to modify the design?
Speed of translation:
Which alternative is quicker to translate to the final implementation?
Accuracy of translation:
For which alternative is the implementation more readily verifiable?
Amenable to final implementation:
Which alternative is easier to implement from?
Recording of tradeoffs:
Which alternative better provides a place for time-space or speed-clarity tradeoffs to be expressed?
Over many years, I've tried many alternative points in the space of design approaches. In my experience, the rapid-prototyping ones all work better than BigDesignUpFront
ones. Further, in my experience, Smalltalk works better than any of the other rapid-prototyping ones if the final implementation can be left in Smalltalk. -- RonJeffries
I'd like to ward off a possible programming languages war coming up, and get back to the intention of this page. I think we have established that the complete "design" lives in the final source code, but that is not what I was interested in to start with. So to make it clearer, I'd like to disallow the final program source code as a contestant. So, if we implement in Smalltalk, then Smalltalk does not get to be the language that would be ExpressingDesignDirectly
, since it will be Expressing Implementation Directly. Or else, there must be some funny way in which it is used so the the "design" of the system shines out, distinct from the implementation. And similarly, if C++ is the implementation language, then it does not get to be the language of ExpressingDesignDirectly
, or it must be used in some funny way. This is how I see to hold the dialog fairly. Other possibilities solicited.
I also go back to what I said at the start, that for me the partitioning and communication paths *are* the design, or the top, key aspects of the design, in a really essential sense. TrygveReenskaug
allows that stuff to be drawn very well, but it doesn't execute. UML doesn't allow it to be drawn very well, and it doesn't execute. IDL picks up the interfaces and types, but too detailed in types and non-executable. Prolog, APL and LISP don't emphasize the modules. C++ is executable but need too much type information. etc, etc, so I end with Smalltalk as a possible language in which one can prototype the design, i.e., the modules (fat classes?), get execution feedback without diving into type information. Now, if I disqualify Smalltalk (implementation) as a design language for Smalltalk projects, what would be the language of design for a Smalltalk project, or what would be the way to use Smalltalk without getting lost in the implementation, so that the design, i.e., partitioning, shines out? -- AlistairCockburn
I feel that I should respectfully decline to play this game. One of the key metrics for a design notation is rapidity of feedback between design and implementation, an essential in incremental development. In any language X capable of expressing design and
implementation, outlawing X for implementation is to play hockey without a stick.
Further to the idea, a question: Given an implementation language X, under what circumstances would one want to use a different design language Y?
To justify using more than one notation, we have to get some benefit in the process or final program, such as:
- Faster development.
- The overall process of producing the program would go faster because of using Y for some parts of the design rather than just working with X. Designing with CRC and implementing in assembler is faster than just designing in assembler.
- Better final structure.
- The final program would be better structured if designed in Y. This would probably relate to difficulty in refactoring language X combined with faster development.
- Easier transmission of design information.
- Some population needing access to the design doesn't understand X, but can understand Y.
- Higher quality.
- Expressing the design in Y makes the implementation in X more reliable, more maintainable, faster. I can't think of how this could actually happen ...
- Team size and distribution.
- Dispersed or or large teams need more permanent artifacts than small local teams. CRC probably doesn't work well with a fully-distributed team.
Exploring in this direction may help us identify key dimensions of designs that are supported more or less well in various notations. This could lead at least to finding good combinations, such as: CRC works well with Smalltalk, UML works well with C++, ...
I see the bind I put you in. Sorry. Now I really don't know how to ask my question. :-) -- AlistairCockburn
What if we talked about RepresentingDesignAspects?
I believe I am more aligned with Alistair here than Ron (than Ron is, or than with Ron).
, as I think, and seems implicit in the discussion here, one should DesignBeforeCoding
, what methodology/notation/language is suitable for expressing those components of 'design' which antecede implementation? I take the intent of TheSourceCodeIsTheDesign
as being that no long-term separately-maintained detailed design document is desired, but I think there's a pre-implementation phase of design where a different sort of notation may be appropriate.
(That does not rule out the use of a particular language system, to me, I just think it implies a different level of specificity.)
I think of design in this sense as following from analysis: it presumes some sense of the domain objects and what needs to be done, and moves into how it is to be done. This is a matter of discovering the implementation modules/classes and their interactions. This seems to me a dynamic process, in which the designers develop and act out a mental model, which can be assisted by semi-physical aids like CRC cards (we've had good luck with a hybrid using OMT object diagram fragments, and occasionally event traces, to act out interactions similarly to CRC).
I'm not sure what the executable
form of this process would be, since to me what's going on is the formation of a model in human minds. I'm not even sure what an executable output of the process would be (an executable design model that is not simply an implementation). Please help. -- JimPerry
Here are three ideas: I know two people who swear by APL for this. They say they can quickly describe the essence of the architecture, plus the algorithms, to test their ideas, and get feedback. I have seen one of these people do this and had long bulletin board discussions with the other, and I won't argue with their success. I wish I knew APL well enough to try it myself.
I do know Smalltalk well enough, and the way I would go about it is to write a small armful of big, fat classes which stub everything and handle a subset of the action, and watch, as we implement
a boiled-down version of the system, for unexpected issues. This could be considered a SpikeSolution
of the architecture, not of any other particular aspect of the implementation.
Harel swears by his StateCharts?
for this. He claims that they also allow both partitioning and execution of an equivalent model. I haven't used StateCharts?
and am only tempted to on nights when the moon is full and the tides high, but there is some attraction to them, particularly for avionics systems.
All the other visual environments I know aren't powerful enough to handle the executability issue. All the other textual environments I know are too cluttered linguistically to handle the rapid variation issue. All the above is terribly personal, but that's where I sit. -- AlistairCockburn
OK, I see that.
Smalltalk lets you quickly implement the guts of a (partial) design and play around with to explore its boundaries and behaviors. You express the design directly in Smalltalk.
I read the original as more proposing Smalltalk as a design notation, addressing not so much the designing process but the artifact passed on to the implementers as expressing the completed design (it can do that too, but that's a different thing). It looks to me like these various senses of 'design' are definitely confusing matters. -- JimPerry
Thanks for the alert catch. I (of all people!) hadn't detected the interwoven aspect of "process" that was in my speaking of ExpressingDesignDirectly
. So it wasn't the thought of dozens of programmers thumbing cheerfully through volumes of Smalltalk code to get
the design :-) that I had in my head at all. It was the thought of a few people exploring the effects of the modularization with the least extra baggage - and now I notice the active verbs in both those sentences. Cool, thanks. -- AlistairCockburn
Jim, you and I just aren't speaking the same language. The implementation is where I learn if my design decisions were correct. I would never use a phrase like "passed on to the implementors". If I was a designer, why would I give up the chance to learn? I think it is more this political side of XP that I'm not communicating rather than anything about what activities go where and how long they last. --KentBeck
There is no "pass on to the developers" in XP. And IMO, that's a strategy that is best avoided always. Even if somehow I needed millions more developers late in the project than in the beginning, I'd want to take a core team, use them to DesignAndBuild?
the essence of the system, then seed development with those individuals as team leaders or such. To "pass on" something as vague and untested as a design in any notation is to lose the best information, the information in the designers' minds. -- RonJeffries
Kent, I haven't seen a lot of detailed input from you on this topic, so I can't say what language you're speaking, but I try to tailor mine to the context at hand, especially if, as here, there seems to be a confusion that can be traced to differing use of language. The notion of a separate design team producing a stand-alone design artifact to be passed on to a distinct implementation team is not something I use or support, but it's a widespread idea in the industry, and seemed to be somewhat implicit in Alistair's GeneratingCppFromSmalltalk
scenario. Anything I've said here was attempting to draw out the details of his intent there into a common language, and has had nothing to do with XP, except insofar as wiki conversations can't avoid that. -- JimPerry
On "the artifact passed on to the implementers" see SoftwareDevelopmentAsaCooperativeGame
and my comments in DesignBeforeCoding
. -- JP
Although I didn't comment on it, I'm glad I misunderstood the XP approach to design; as of a few days ago it seemed y'all didn't officially approve of any DesignBeforeCoding
, and now it seems XP does more design than anybody, and only disapproves of whole gruntloads
(which latter I have yet to see anyone here defend as such). It seems to me today as if virtually everyone is singing from the same choirbook. -- JimPerry
Just a minute, I'll think of something to disagree with, even if I have to disagree with myself. -- RonJeffries
Hey, Ron, a very long minute has gone by. I'm waiting to see you disagree with yourself ;-) Or have you caved in and ended up agreeing? -- Alistair
I assume that Ron's lack of a response indicates that he found nothing to disagree with, an obvious disagreement with his believe that he would disagree. Clearly, he was right!