Summary
Almost everyone who teaches object orientation uses
the class as a fundamental building block.
Such an approach misses the central point of object
orientation: the objects themselves, and what they
portend for flexibility and effective design.
This weblog is a case study in teaching object orientation.
Advertisement
Welcome
Welcome to my new blog!
It's a pleasure to be here among such good company.
This is my first blogging foray, and I'm looking forward
both to exploring this new medium and to using the medium
for exploring my own learnings together with the rest of you.
It may be good to start with introductions.
I am an Electrical Engineer and Computer Scientist
by training, having received degrees in these
fields in 1977 and 1979, respectively.
I capped off my education with a Ph.D. three
years ago.
Most of my work career has been at Bell Laboratories,
where I started in 1979.
I spent my early Bell Labs years on a large
development project and then moved on to a technology
transfer organization, where I spent more than a decade
doing early work with the C++ language,
with distributed workstations,
and version and configuration management.
When I left Bell Labs in 2001, I had been in the
Research area for about 10 years.
Most of my research focused on software architecture
(including the foundational work on software patterns) and
organizational structure.
I am a long-time critic of some of the value systems
and practices of academics in general and of academic
computer science in particular.
I have worked over the past decade to gain
first-hand credibility with academic culture, both
to further my understanding of the issues and to
gain the credentials that might one day allow me
to change the field from the inside.
That's where I am now, and that's what I do.
I teach computer science at
North Central College,
and also teach discrete mathematics and English composition.
I am also the
Vloebergh
Professor of Computer Science
at Vrije Universiteit Brussel
and am a
Visiting
Professor of
Computer Science at
University
of Manchester (formerly UMIST).
I plan on using this space to reflect on experiences
I haven't yet committed to writing, and particularly
my recent experiences as an educator.
I frequently admonish my English composition
students with Forster's saw:
"How can I know what
I think until I see what I say?"
I hope that mindset serves me well here,
and that it provides you an opportunity to challenge
your worldviews and to respond in your own
pen with your own thoughts.
Teaching Design
At the
OOPSL
A
1999 Educators' Symposium, I emphasized
the importance of teaching design in undergraduate computer science
curricula.
I'm trying to put my money where my mouth is now that
I'm in that position.
I taught object-oriented analysis and design this term.
It became an interesting opportunity because it forced
me to think about what's really important about objects:
one can leave only so many ideas in a student's head
over the course of a few short weeks, so it's important
to make a lasting impression about the key elements.
It would have been easy enough to focus on the standard
set of principles: coupling and cohesion, perhaps
modularity, and of course the piece de resistance,
polymorphism.
But I found it difficult to justify these principles from
any value proposition that I felt I could sell to the students.
So it was time to go back to basics, and that's what I did.
And of course I wanted to feature the main attractions of
contemporary object-oriented analysis and design.
The CS department is driven to a large degree by input
from an industry board.
That board conveys pressing industrial needs, and we respond.
We add formal foundation courses to round out the
collection of courses.
So in the interest of giving students something
practical and current, I knew that both Use Cases
and CRC cards would figure strongly in the material.
A Two-Pronged Approach: Function and Structure
What I ended up doing was to present design as a two-pronged
excercise: structural design, and functional design.
Structural design gives a system the long-term stable
structure that can reduce discovery costs,
localize maintenance work, and provide a foundation for reuse.
The main component of structure--in the conventional
view--is the system classes and the relationships
between them.
The other perspective is functional design.
Though it featured more strongly in some of the
earliest design approaches for computer programming,
it has made a resurgence in object-oriented
days in the guise of Use Cases.
Both structure and function are important to
profitability.
When we think of profitability we most often
think of the functional side:
What can we sell, and for how much?
The functional side is directly visible to
the customer.
Function is what customers are willing to
spend money for; it is the direct customer
value that software enterprises deliver.
A common view is that
good function, delivered in a timely fashion,
is the hearbeat of a thriving enterprise.
Profitability isn't only about revenue,
but about cost as well.
Good structure holds down
development costs by localizing change.
It might also reduce cost by making the code
easier to understand and hence to modify.
Even though customers don't care about internal
structure--they probably don't even see it--they
will pay a price for poor structure in feature
delivery schedules and perhaps even in the very
feasibility of some features.
Experience tends to bear out that poor design
shows through all the way to the end user, too,
as Brenda Laurel points out in her seminal book
Computers as Theatre (Addison-Wesley, 1993).
These are competitive considerations in
the marketplace, considerations that affect
the revenue stream.
Beneath these factors lurks the increase in
raw development cost that owes to
poor structuring: long discovery times,
or more intense coordination across major interfaces.
These last few paragraphs seem to have sidetracked
us from a focus on good object-oriented pedagogy to
business practices.
I bring up the business perspective not so much
because I feel that academia should take industry
as its primary client.
Computer science to the contrary not withstanding,
academia has a long legacy of being the cradle
of great new ideas whose relevance isn't appreciated
until many years after their "discovery."
However, industrial practice is often a good
litmus test for the viability of our design models
and of the teaching models that convey them.
I highlight this dichotomy between structure and
function because it relates directly to how software
design is often taught, as well as because it can
relate to the "real concerns" of the business world.
We have seen the history of software development
pass through fads that cycle back and forth
between structure and function.
Structured design is often caricatured as relating
to structure.
It was followed by structured programming, which
focused more on program flow (function) than on
the structure per se; structure was subordinate
to function.
Then came abstract data types, and slightly later,
object orientation: the functional view got the short
shrift.
Finally, came Use Cases: a noble attempt to resurrect
the functional view.
That's where we are now.
I believe there are some simple ways to
integrate the functional and structural view.
This integration has some surprising results
for how we view object oriented design and
its activities, and has repercussions that
go far beyond pedagogy.
Let's have a look at the common contemporary
processes of object-oriented design and
contrast them with a simple alternative
view.
Classes, Objects, and Other Things
Teaching OO: The Class-ical Way
If you look at most syllabi to seek out the single
most fundamental concept of object-oriented
programming, I'm guessing that we'd find it
to be the class.
If you ask people about object-oriented design
notations such as UML, most people naturally think about class
diagrams.
Object diagrams and dynamics are almost always
secondary to the class model.
Even when faced with an object model of their
own making, most programmers have difficulty
answering the question: "Where did that
object come from, and where was it created?"
We extrapolate our static source code view into
how we model the application as a whole.
Maybe we do that to avoid the complexities of
the highly dynamic object structure;
an object model either can capture the
relationships as they exist at a single
moment in time or, as is more likely done,
combine some relatively arbitrary collection
of relationships that cover a span of execution.
But class models already capture many such
relationships anyhow.
If you ask people about the building blocks
of object-oriented programming they will
also likely mention classes.
Most popular programming languages use
classes as their basic building block.
Classes are the foundation of object-based
and object-oriented programming in C++.
They are unavoidable in Java and Smalltalk.
Thinking ahead to coding, most designers
bring the programming constructs into
their design thinking.
This is a natural and healthy
practice--but as all practices must be
tempered with other considerations as
we'll see later.
Trygve Reenskaug
(author of Working with Objects,
Prentice-Hall, 1996)
notes that this is pretty funny:
we call it object-oriented programming,
yet we tend to focus on classes.
There are some strong cognitive reasons behind
the human tendency to focus on classes.
Humans love to classify and organize to help
their understanding.
Classes are a way of grouping lots of related
objects from the perspective of structure.
We feel a sense of power in this grouping.
What's more, we become a bit drunk on this
same power when we discover that we can group
related classes together into a hierarchy
under a single base class.
Classes become king.
This isn't the first time that the class
tradition has come into question.
The self programming language,
pioneered by Dave Ungar and Randy Smith, demonstrated that
a real programming language based on objects
instead of classes could deliver powerful
flexibility and convenience.
Both Ungar's vision of flexibility and
Trygve's vision of objects would find
vindication later in history as components
became popular.
Components are heralded for their improved
flexibility over objects, something I suspect
Ungar always had in mind.
Trygve Reenskaug, on the other hand, said
that components were what he always
envisioned object-oriented programming to
be from the beginning.
Classes have prevented these two visions
from flourishing and in fact may make
it difficult for fledgling practitioners to
appreciate the fundamental benefits of
object orientation itself--particularly
the benefits of combining the structural
and functional views.
Even though we have Use Cases in a very few
contemporary course syllabi, classes rule in
software engineering education.
We tend to keep Use Cases in our back pocket
in case someone asks where we capture functional
requirements.
But they tend to fall out of our back pocket
and get lost once we move on to class design,
based perhaps on the misplaced belief that
the class member functions capture all
we need to remember about the functional view.
And the classes have a strongly hierarchical
nature to their structure.
But there are two problems here:
the functional view
still is important, and that the world
is rarely very hierarchical.
We can "make" the world appear hierarchical
from a structural view.
But it is rarely possible even to reconcile
the functional view with this hierarchical
structure.
And because the functional view is key to
what generates your key revenues, that's a
problem: you don't sell classes, you sell
functionality.
Teaching OO: The Next Generation
Much of object-oriented pedagogy (and perhaps
of pedagogy in general) seems to be based on hierarchy.
The high point of many expositions of object orientation
comes with the revelation of inheritance hierarchies
supported by run-time polymophism.
I think this tendency to hierarchy comes from our
need to organize--and that's fine--but I think
it goes too far in most expositions of object orientation.
It often goes so far as to eliminate information
to reduce apparent complexity.
There is a term for the elimination of information: abstraction.
While we want to organize essential complexity and
minimize accidental complexity, it is dangerous to
put aside elements of essential complexity.
Such elements will be important either in an early
offering of the system or will become important
as the system evolves.
It's best to put the right framework in place
for these "details" up front; it may be
almost impossible to add them later.
Mies van der Rohe said, "God is in the details."
Hierarchy has become an important abstraction
tool in many design paradigms.
Used effectively, it brings organizational
power.
Used to shed essential complexity, it is evil.
In most object oriented design, most abstraction
is evil.
It is an excuse to ignore things we don't
want to deal with even though we should.
We start to reduce complexity by grouping
objects together into classes, which is
in accordance with how most popular programming
languages work.
These programming languages are popular because
they are efficient.
But then we take an overly casual and slightly
dangerous leap from this hierarchy of objects
to hierarchies of classes.
Why is this dangerous?
There are several ways to describe this danger,
but I'll focus on one.
When we group objects together the result isn't
an object: it's something different, a class.
That's a healthy distinction that helps the designer
look at a program in two useful ways:
the dynamic structure of objects,
and the static, source-code structure of classes.
But when we combine a hierarchy of related classes
under a common construct that groups them together,
we too often just use the concept of "class" again.
The problem is that it's not a class any more:
it's not a single structure that captures the
structure of all the objects of all the classes
being grouped together.
Making this level of abstraction into a class
discards the information that the resulting entity
stands in for a larger number of classes in the
subtending inheritance graph.
Roles to the Rescue
This perspective precipitates two interesting insights.
The first is that for a class-based OO educator,
this level of compression points out
a missing concept: the elusive concept that
ties related classes together.
That missing concept is a role and
has long been featured in what were considered
to be offbeat design methods like Reenskaug's
OORAM.
A role characterizes part of the interface of an object,
such that the responsibilities characterize some sphere
of knowledge or influence.
A given object can take on several roles at once.
Consider a Circle object as an example: we can
ask it to yield its circumference, location, or area;
we can ask it to move, rotate or warp:
these owe to a role we might call Shape.
We may also want Circle to respond to requests
to draw itself on some output medium, or to
change its color: these owe to a role called Drawable.
An image file object might also respond to all
the responsibilities of Drawable, though that may
be all that images have in common with Shapes.
The second insight is that progress in programming
languages has caught up with this reality:
roles appear as a first-class programming
construct in the guise of Java interfaces.
There are interesting corrollaries to these insights.
The first is that roles are more about objects than
they are about classes.
A class is a total classification of objects.
Rather than thinking of a role as a partial
interface to some class,
it might be better to think of it as a
partial classification of a set of objects.
To me, that suggests deferring classes
until students have mastered the concepts
of objects: the grouping of responsibilities,
and the colocation of active data and the
functions that operate on them.
Second, because they are not total classifications
roles break down the tyrrany of hierarchy.
That is a better match for the real world.
When God created the world, she did not create
it as a hierarchy of classes.
She may not even have created it, as Kant might
insist, from a universe of discrete, identifiable
objects.
Roles provide the freedom to define a software
reality that can align with a myriad of important
design perspectives that range from the marketing
view to the structural view.
A class is, after all, just an implementation
of what might be a degenerate kind of role.
Third, because roles are closer to objects,
they are closer to the structure of Use Cases
than classes are.
Objects are run-time animals, and the role
interface to an object reflects a set of
responsibilities related more by some function
than by any structural consideration.
Yet as partial classifications, roles can
also bridge the gap to the structural world.
This is perhaps the most powerful contribution
of roles: as a locus for the intersection
of structure and function.
Pedagogical Reflections on Design
My challenge at the beginning of this term was
to sort out the whole notion of object-oriented
design for cogent presentation to a wide variety
of students.
I had a hunch that an object-based focus
would win out over a class-based approach
(in terms of comprehensibility and conceptual
integrity).
And I followed the haunting voice of Trygve
in the back of my head, both with regard to
the centrality of objects and with regard
to the place of roles in design.
The result was wonderfully satisfying.
Very early in the class, perhaps on the first
day, I introduced the traditional design
dichotomy between function and structure.
I put this in the context of design approaches
that historically preceded objects in their
own fifteen minutes of fame.
That objects were not an end-all and be-all
would be a recurring theme in the course,
though the course itself focused on objects
without going into other approaches in any depth.
I then introduced a simple notion
of objects as loci of structure and behavior.
From the outside, all we see of an object
are behaviors through which we can ask it to do
things on our behalf.
That was a natural lead-in to abstract
data types, with a careful emphasis on the
"abstract" and "type" parts of the moniker.
Note that students faced ADTs quite a bit
before they would encounter classes.
I avoided class and language issues, but
focused on things that are important from
the perspective of Conway's Law--the rule
that says that software architecture exists
mostly for the sake of the structure of
the organization that builds it.
With those ideas grounded, I could move
on to classes, but more as a convention
of packaging than as any important unit
of intrinsic structure.
At about the same time I introduced roles
as being the analysis or design counterpart
of what we had been talking about as ADTs.
I made the perfunctory concessions to C++
and its convention to use pure abstract base
classes as a way to capture the semantics
of roles and ADTs, and appealed to the notion
of Java interfaces with which they were already
familiar.
Next I introduced Use Cases.
We introduced fat and thin Use Cases following
a conventional exposition, using Alistair
Cockburn's Writing Effective Use Cases
book (Addison-Wesley, 2000).
Then, and only then, did I introduce CRC cards.
CRC cards are the place where the structure
of classes comes together with the dynamics of Use Cases.
A hands-on CRC exercise provided the students with a vision of how
dynamics help shape the structure, and how the
structure yields insight into the dynamics.
For me, this was the high point of the
object modeling part of the course.
It represents the central essence of object orientation.
Oh, yes, we went on to do inheritance and
polymorphism to round out the picture,
and later went on to more advanced concepts
including reflection, aspects, and most other
buzzwords of the contemporary object-oriented
arena.
We also covered the perfunctory issues of
covariance and contravariance, building largely
on the Liskov Subsitutability Principle but
more broadly grounding the issue of subtyping
in Bertrand Meyer's taxonomy of IS-A inheritance,
supported by Design By Contract.
And of course we covered patterns and a few
more popular topics.
But more importantly we came back and reflected
on where we had been, and critiqued the
various structure techniques much as one finds
in the discussion of the piece you're reading here.
CRC Cards Tie it All Together
CRC cards were created by Ward Cunningham
(see his blog at this site) back in the
Smalltalk days at Tektronix (or perhaps it was at Wyatt).
Smalltalk features classes as its staple building blocks
so it was natural to take those concepts into the
design arena.
But a programming language class conveys both
behavior and structure, while the CRC card
approach quickly settled on a responsibility-driven
approach.
CRC cards are all about what an object can do
rather than being about what an object is.
In fact, they look more like roles than like
classes!
Kent Beck, who has worked closely with Ward
over the years and who has done much of the work
to popularize CRC cards, once remarked in a workshop
that CRC cards weren't really about classes but
about roles.
In fact, CRC cards are a powerful hybrid representation
that brings classes, objects and roles together.
When Kent and Ward do CRC card exercises, they tend
to think of a card as an object when you are holding
it in the air, and as a class when it's on the table.
The responsibility focus is a way to keep the design
close to the Use Cases:
Use Cases come down to collection of responsibilities,
and object-oriented design is in large part the
activity of grouping those responsibilities together.
CRC cards do that.
The resulting entities may or may not be building
blocks; what makes a good building block depends
in part on embedded software, available software
packages, and even tradition.
CRC cards can capture that, too
This perspective on Use Cases, objects, roles and classes
let me integrate them together around a small number
of intuitive concepts.
If students understand what responsibilities are, they
can understand Use Cases and can certainly understand roles.
Looking at objects as locales of structure and behavior
makes object-oriented design "real" in terms of the programming world familiar
to them, and bringing in the concept of classes as optimizations
(sharing member function code and a structural skeleton across objects)
makes it concrete in terms of a programming language.
Rather than clumsily introducing Use Cases as a front-end
to the "find the objects" exercise, or of explaining the
similarities and differences between responsibility-based
design and some other flavor of object-oriented design,
this approach serves to point to a larger, single
underlying model of which classes, objects, Use Cases
and roles are just facets.
It is this underlying model that I would call
the object paradigm.
By the end of the course, students could tie together
the basic concepts of responsibilities, objects, classes,
and roles.
They understood how Use Cases fit into the process.
They understood the interplay between the functional
and structural views of the system as embodied in
Use Case responsibilities and classes respectively--a
view that takes students all the way from the classes
of programming to the organizational structures that
separate functional concerns from structural concerns.
I'm guessing that most people who teach CRC cards
teach them as classes rather than as roles.
People gravitate toward classes for the same reasons
we discussed earlier: reducing the amount of information
one must deal with, and talking about design in terms
that already are familiar from programming.
I am concerned that this misses the essential
foundations not only of CRC cards but, more worrisomely,
the responsibility-based foundations of object orientation
itself.
And here's the punch line: it isn't only pedagogy that
falls short on these issues.
Most designers in the real world tend to work the same way.
It is at least sad, and perhaps scary, that most people
are using object orientation in a way that is based
on modules with polymorphism and instantiation rather
than on a more living design approach that embraces
Use Cases and the dynamic view that objects bring.
Beyond Pedagogy: Fundamentals of Design
In some sense, one can look at this exercise in crafting a
course on object-oriented analysis and design
as an exercise in building an object model.
It's important to understand that I didn't approach
it that way.
I focused on fundamentals, fundamentals
that led to fundamental benefits such as ease of
evolution, accommodation for Conway's Law,
software compression, and relationship to business goals.
It was a quite un-academic tact.
A more academic tact would have started either
with programming language or perhaps wth type theory
and the semantics of inheritance.
It was satisfying to see that this approach tied to
the fundamental notions of design in a way that
may not be satisfying to someone looking to tout
the benefits of a given programming language or
methodology, but that might be more satisfying to
someone with a degree in engineering or architecture.
Design is the collection of activities and tools that
take one from the understanding of a problem to its solution.
What problem you are solving?
In a companion course on Systems Analysis,
we teach students that this is one of the most
important questions you can ask.
This question is too often lost in most contemporary
object-oriented development, since objects focus
more on the structural component of design than
on the functional leg of design.
There was an activity in the 1970s called the
"design movement" that included people as disparate
as Peter Naur (the "N" in "BNF") and Christopher
Alexander.
(See Developments in Design Methodology
by Nigel Cross, Wiley, 1984.)
Much of their work focused on the interplay back
and forth between the problem domain and solution
domain.
The "problem domain" brings customer desires and
needs.
What the design movement learned is that this
customer view should be tempered with the realities
that unfold during design.
In software, we know this as iterative design.
In the object-oriented analysis course we
typified the solution component as the class
structure, and the customer problem component
as the Use Cases.
CRC cards are the place where these two worlds
come together--where struggles with the solutuion offer
insight into the problem itself.
Reconciling these forces both keeps the customer
happy by meeting functional requirements,
and keeps the enterprise happy by leading
to a structure that best accommodates evolution.
Infusing roles is a good lead-in for many other
features of the object community.
Aspects can be described as collections of
roles in a more straightforward way than
is feasible from a basis in classes.
The focus on Conway's Law is a direct
lead-in to refactoring.
These results are not just academic.
They do in fact lead to an object model
and a design approach that accommodates
that model.
But it is more than an object model: it
is also a business model and a process
model, a model that is practical,
teachable, and perhaps even powerful.
What, in summary, is the development approach
based on that model?
Elicit functional requirements from
customers and other stakeholders and
capture them as use cases.
In parallel, capture structural and non-functional
requirements that come from the embedded base and
from domain experts.
Use CRC cards to iterate the Use Cases and
class structures against each other.
Precipitate classes and roles from the CRC
cards.
Classes come from total classifications,
and roles are partial classifications that
relate to Use Case-centered concerns
Code it up, and use the insights
from the coding experience as input
to further iterations of the CRC exercise.
That's it.
On one hand, none of the notions are individually
profound.
But on the other hand, this perspective
combines a small number of fundamental
concepts into a consistent, integrated
picture of the fundamentals of object
orientation.
Thank you for this excellent exposition! I wholly agree with the emphasis on role rather than class or any other packaging unit. An interesting question than becomes the definition of a role. How do you identify roles and what is the relationship between use cases and roles? In the business domain I have found the DEMO approach (http://www.demo.nl) thought provoking in this area.
The Smalltalk notion of method calls as messages should be noted, which brings to mind a living system with autonomous objects in play. In fact this may give the impression of a more magical system than in fact it is -- one can reduce that system to something more mundane fairly easily (and of course the implementation generally does just that).
When you say that a piece of code tells (or asks) an object to do something, you imply that the message -- the verb, qualfied by the arguments -- is central, with the object being the actor by delegation. How that object does what it does is up to the object, which may delegate to its class, or who knows what. Of course, in mundane languages (like Java) you pretty much know that the object is going to use its class's function definition. But in more exciting languages, like Smalltalk or Python, you can play with classes and methods rather easily, and a method call really is a message.
It's a digression, but I think it is interesting to note that Python actually has a loose notion of classes -- one can certainly use it like a normal OO language, but it is also quite easy to use it as a more prototype-based language, ala Self. This is because the basic operations -- getting an attribute, calling an object, defining a class, etc. -- are all very concrete. The result is a programming model that is about doing rather than declaring, and execution is far more manipulable than declaration.
As another digression, I think programming is a craft, and design is best learned through thoughtful reflection on failure (which is actually true of most skills, particularly intuitive skills). That is to say, the real way to teach design is to have students design ambitious things, implement them, most likely fail (at least on some level the product won't live up to their ambition), and having failed reflect on that. They will fail in typical ways no doubt, but they will be far more ready to learn about solutions once they truly recognize the problems. They will also recognize the problems early on, for they will have experienced those problems before they became problems.
This is especially important in school, because in school you can fail safely, and you can admit that without fear (at least in a good class). That's hard later on in life, unless you do other programming on the side (which good programmers do). This was certainly how I learned programming -- though that may itself discount my claim ;)
There is certainly a lot in common between the object paradigm I attempted to teach in this course, and the component model espoused by knowledgable writers such as Szyperski. I think your work is in that spirit, and I applaud your efforts!
BTW, though, I think that as a pattern your exposition at http://www.theserverside.com/patterns/thread.jsp?thread_id=17595 needs some refactoring. Try splitting it up into more atomic pieces; most patterns are small things, and this is pretty large. Second, a pattern must build something structural: let each of your patterns focus on what is built (a use case, event flow, component, etc.) The built parts should compose into some "whole."
> It's a digression, but I think it is interesting to note > that Python actually has a loose notion of classes -- one > can certainly use it like a normal OO language, but it is > also quite easy to use it as a more prototype-based > language, ala Self.
Python was one of the languages of choice for students working on the project in this course.
> As another digression, I think programming is a craft, and > design is best learned through thoughtful reflection on > failure (which is actually true of most skills, > particularly intuitive skills).
One of my main inspirations for teaching is Carroll's minimalist model, where failure plays a central role. In this course -- as in most upper level courses I teach -- there was a "live project" requirement. Students were required to do a project for a real industrial client. One of the projects resulted in a code framework that is going into production for a major international manufacturer and retail firm. Another project laid foundations for process changes in a large pharmaceutical firm.
> This is especially important in school, because in school > you can fail safely, and you can admit that without fear > (at least in a good class).
I think that's true in the more elementary phases of pedagogy. I commend Carroll's book to you: The Nürnberg Funnel. Check it out.
Absolutely excellent. The more I gulped down, the more I kept getting the feeling that somewhere this is relating to something I allready feel or think. For me, I think it is the fact that I view things with RDD colored glasses. I suspect that's why so much of what you said just simply 'gelled'.
Very very minor suggestion, but you might mention the Newton (NewtonScript) and JavaScript as examples of production prototype-based object models. Of course, NewtonScript is now forgotten and most people aren't even aware that JavaScript /has/ an object model, even though all programming in the language uses it implicitly.
But then, I'm a prototype/object bigot... it just makes 1000 times more sense to me than having classes. Guess that's why I've written Web servers in JavaScript and haven't learned Java yet...
Indeed, I don't think many people realize that JavaScript can be suprisingly OO--although OO code in JavaScript can look fairly unrecognizable as such. Still, you can do base classes (prototypes), constructors, inheritence, polymorphism, information hiding, class and instance methods and class and instance properties. I don't think it is leveraged very much though (too bad).
I think the focus on classes is largely a function of the textual representation of a program. It's difficult to represent an object in text at design time. Objects are more easily creatures of runtime. Classes are unatural in that we seldom interact with classes in the real world. It's a big leap to code in classes while visualizing the complex runtime interaction of instances.
Very interesting and promising work. I have a few comments and will do one at the time.
First a bug in the blog: A title towards the bottom is coded: "<h1>Beyond Pedagogy: Fundamentals of Design</h2>" MSIE and Netscape ignores the bug, while my Opera browser takes the code literally, showing the rest of the document in large bold font.
Re: A Two-Pronged Approach: Function and Structure: "Profitability isn't only about revenue, but about cost as well. Good structure holds down development costs by localizing change. It might also reduce cost by making the code easier to understand and hence to modify. "
Trygve comment: The relationship between structure and correctness is most important. -------------------------------------------------------------------- ----------------- Edsger Dijkstra's famous observation: "Program testing can be used to show the presence of bugs, but never to show their absence!?
There is currently a deplorable trust in testing. It is impossible to test quality into any product.
My assertion #1: "With a given test regimen, the number of bugs shipped is proportional to the number of bugs found during testing."
When launching Windows 2000, MS bragged that they had found 60.000 errors during testing! They bragged about it! Not realizing that they bragged about their programmers' sloppiness.
My assertion #2: "Correctness has to be designed into a product. The purpose of testing is to confirm its correctness. Any bug found during testing is to be regarded as a setback and an indication that there is something wrong with the creative process". This is true for an extreme programming kind of process as well as a RUP process.
My assertion #3: "Every problem has a simple solution? By 'simple' a mean a solution that can be mastered by a human brain. Consider a modern car. It is a very complex device. Yet as a driver, I have a simple mental model of what it is and how I can master it. I also imagine that all its subsystems can be equally simple and mastered by the relevant experts.
So structure is about correctness. Structure is about simplicity. Structure is certainly about cost. Development cost, maintenance cost and cost to the end users. How many millions of money is wasted because our software stinks?
Re: A Two-Pronged Approach: Function and Structure: "The functional side is directly visible to the customer. Function is what customers are willing to spend money for; it is the direct customer value that software enterprises deliver."
"Even though customers don't care about internal structure--they probably don't even see it--they will pay a price for poor structure in feature delivery schedules and perhaps even in the very feasibility of some features."
Trygve comment: User's Mental Model important. -------------------------------------------------------------------- -- May be true, but is a great pity. Donald Norman (Design of everyday things) claims that it is equally important to support the user's mental model. This is related to structure. I claim that it is the responsibility of the software developer to give the user a workable mental model. Make the user understand not only what the system does, but also how it does it. (Function AND structure at the level of the user's mental model)
A modelling language for the mental model could be an object based language, i.e., a language describing object structure, object responsibilities, and object interactions. In other words, a role modelling language. Class structure is an implementation detail that is irrelevant to the user.
Users should see the system structure. This will cause them to care about it.
Cope teaches future computer professionals how they can think about the programs they develop. I.m.o, we also need to understand how users can think about and master the programs they use. Alexander's "the quality without a name" is relevant here. Build habitable systems!
Re: Teaching OO: The Class-ical Way: "Components are heralded for their improved flexibility over objects, something I suspect Ungar always had in mind. "
Trygve comment: The UML 2.0 Component is a class; its instances are objects. ---------------------------------------------------------------------- ------ The UML 2.0 notion of a Component is interesting. The Component metaclass is a subclass of Class, so its instances are objects. The Component specifies provided and required interfaces. It encapsulates its contents.
From the UML definition: "If more detail is required of the role or instance level containment of a component, then an internal structure consisting of parts and connectors can be defined for that component. This allows e.g. explicit part names or connector names to be shown in situations where the same Classifier (Association) is the type of more than one Part (Connector). That is, the Classifier is instantiated more than once inside the component, playing different roles in its realization. Optionally, specific instances (InstanceSpecifications) can also be referred to as in this notation."
So a Component may encapsulate objects. They are called its Parts and are handled as attributes. The Parts are interconnected by Links. The Parts can be instances of Components or plain classes.
It seems to me that the UML team has made an important step forward from my many attempts at describing roles. I have always thought of objects as encapsulated. The encapsulation separates the object's external properties (UML: provided and required interfaces) and how it is realized inside.
I think of e.g. Smalltalk methods as residing within the object. The purpose of the class is to reduce coding. The purpose of class inheritance is likewise to reduce coding. Applaudable things, but completely uninteresting to the end user.
Re: Teaching OO: Roles to the Rescue: "A role characterizes part of the interface of an object, such that the responsibilities characterize some sphere of knowledge or influence."
"Third, because roles are closer to objects, they are closer to the structure of Use Cases than classes are. Objects are run-time animals, and the role interface to an object reflects a set of responsibilities related more by some function than by any structural consideration. Yet as partial classifications, roles can also bridge the gap to the structural world. This is perhaps the most powerful contribution of roles: as a locus for the intersection of structure and function. "
Trygve comment: The role is an object in the context of a function. ------------------------------------------------------------------- C onsider a function that is realized by a number of interlinked objects; each object being responsible for a certain part of/aspect of the function.
Consider a use case where an actor shall fill in his name, address etc. Let there be five fields for name, street address, ZIP, city, and phone number.
This can be realized by a form object (instance of DialogBox) that encapsulates five field objects (all being instances of TextEditor). Each field provides an interface towards the actor and requires an interface to some Person object in the background. There are provided and required interfaces between each TextEditor object and the DialogBox object.
We can provide sub-functions simplifying the actor's work. If the actor fills in the ZIP, the city name can be automatic and vice versa. If the actor fills in the phone number, it is conceivable that the full address could be retrieved automatically.
Each of these sub-functions can be defined by a suitable MSC showing how objects interact to realize the sub-function.
The realization of functions and sub-functions can conveniently be discussed with CRC cards. CRC cards are all about what objects *do* rather than about what they *are*. In fact, they look more like roles than like classes! (In my book, I said that "The CRC technique supports role modelling directly, since both focus on object responsibility and object interaction." I even considered renaming them RRC-cards, but thought this would be going too far out.)
As a side issue: I believe that users' mental models could be role collaboration models. A programming environment based on collaborations and roles rather than classes and subclasses could be a new Smalltalk.
Flat View: This topic has 27 replies
on 2 pages
[
12
|
»
]