Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SoA Vs OO

8 views
Skip to first unread message

Generic Usenet Account

unread,
Jun 2, 2004, 7:14:11 PM6/2/04
to
For the past decade and a half, the software industry mantra has been
OO. We have heard repeatedly that an object-oriented design is more
maintainable, more reusable and more resilient to changing
requirements. Now suddenly the air is abuzz with Service-oriented
Architecture. Object-orientation does not seem to be cool any more!

When I take a closer look at SoA, it seems a lot closer to functional
design than object-oriented design. When I look at services, I tend
to look at them in functional terms AND NOT object terms. Whatever
happened to those oft-repeated protestations that functional
decomposition is bad and object-orientation is good?

Am I missing something, or is the pendulum swinging back towards
functional design? Whatever happened to those neat concepts like
inheritance and polymorphism?

Bhat

Michael N. Christoff

unread,
Jun 2, 2004, 7:49:33 PM6/2/04
to

"Generic Usenet Account" <use...@sta.samsung.com> wrote in message
news:90e5135.04060...@posting.google.com...

Web Services Description Language (WSDL) Version 2.0
http://www.w3.org/TR/wsdl20/#Interface

From the site:

2.2 Interface
2.2.1 The Interface Component
An Interface component describes sequences of messages that a service sends
and/or receives. It does this by grouping related messages into operations.
An operation is a sequence of input and output messages, an interface is a
set of operations.

An interface can optionally extend one or more other interfaces. In such
cases the interface contains the operations of the interfaces it extends,
along with any operations it defines. The interfaces a given interface
extends MUST NOT themselves extend that interface either directly or
indirectly...etc...

----

l8r, Mike N. Christoff

Ian Woods

unread,
Jun 2, 2004, 9:11:18 PM6/2/04
to
use...@sta.samsung.com (Generic Usenet Account) wrote in
news:90e5135.04060...@posting.google.com:

> For the past decade and a half, the software industry mantra has been
> OO. We have heard repeatedly that an object-oriented design is more
> maintainable, more reusable and more resilient to changing
> requirements. Now suddenly the air is abuzz with Service-oriented
> Architecture. Object-orientation does not seem to be cool any more!

It has been accepted for some time that there is no automatic way of
making good software. No technique or methodology automagically generates
maintainable, reusable and robust code.

Why is OO good? It builds on well understood concepts from other
techniques: modularity and loose coupling between modules. All good
programming techniques which I've encountered are based on these two
concepts. OO is good because it applies these concepts well and adds
sound guidelines and concepts which simplify the practical problems of
reusing code and determining the responsibilities, ownership and
interface of real modules.

<snip>

> Am I missing something, or is the pendulum swinging back towards
> functional design? Whatever happened to those neat concepts like
> inheritance and polymorphism?

They're alive and well...

IMO, you're missing some key points from the last 70 years of programming
and computing history.

o Way back when companies bought non-programmable punch-card machines for
specific tasks, such machines were developed so that the card output of
one machine could be easilly fed into another. This allowed more complex
tasks to be performed than any single machine performed, and provided the
ability to reuse the same machines in a different way to perform
different tasks.

o The flexibility of the unix command line is a direct consequence of the
ability to use simple tools with well defined interfaces to get more
complex behaviour. Each of the tools (typically) run independently being
loosely coupled by the chaining of output to input provided by the shell.

o Classical object oriented languages (like Smalltalk) work on the model
that each object is a seperate black box with a defined interface, and
more complex behaviour is formed by objects sending messages to other
objects in the system. Later 'statically typed' OO languages dropped the
loose coupling of objects in order to promote compile-time type safety
AFAICS.

The principals of SoA have been discovered, rediscovered, repackaged and
reused over and over again. There's no doubt plenty of other examples
where these principals have been conciously applied before which I'm not
aware of. Each incarnation is different because it's overall purpose is
different, and different decisions need to be made.

Loose coupling between black-box modules has been, and will continue to
be, a very useful way of making more complex behaviour out of less
complex components - and I have every confidence that they will outlive
any kind of 'coolness' factor of any technology based on them.

Inheritence, with these principals in mind, is simply one way of deriving
a 'new' black-box module from an existing one. It's an example of reuse.

Polymorphism, with these principals in mind, is simply one way of
creating a series of black-box modules which have compatible interfaces
but (potentially) different behaviour.

The concepts of inheritence and polymorphism haven't suddenly become less
useful - they will enhance practically any technique where loosely-
coupled-black-box-modules are used, including SoA.

Ian Woods

--
There is no sig.

Joachim Durchholz

unread,
Jun 3, 2004, 3:05:44 AM6/3/04
to
Generic Usenet Account wrote:

> When I take a closer look at SoA, it seems a lot closer to functional
> design than object-oriented design. When I look at services, I tend
> to look at them in functional terms AND NOT object terms. Whatever
> happened to those oft-repeated protestations that functional
> decomposition is bad and object-orientation is good?
>
> Am I missing something, or is the pendulum swinging back towards
> functional design?

Functional decomposition is very different from functional programming.

Functional decomposition means: Start looking at the high-level
functions, leave details open, then refine. Works well until you find
that the details hide lots of nasty devils.
I don't think that functional decomposition - as a design method! - ever
fell out of favor. It's the only sensible way to get software that does
what you want. (Coding usually works the other way round, bottom-up,
simply because it's easier to test that way.)

Functional programming is different. It's about composing functions at
run-time and passing them around as data until some other part of the
program needs to call them, usually accompanied by avoidance of internal
state. The former makes functional programming extremely powerful, the
latter safer.

> Whatever happened to those neat concepts like inheritance and
> polymorphism?

Inheritance and polymorphism as typically done in OO languages are a
mixed blessing: they have massive advantages, but each of them comes
with their specific problems and shortcomings. (The Design Patterns book
shows this - there's simply too much boilerplate code in it, a single
line of boilerplate per design pattern should be the maximum.)

Functional languages still do inheritance and polymorphism. The
approaches are just very different, with a different mix of advantages
and disadvantages.
(The difference is that I see ways to remedy the disadvantages to
irrelevance in typical FPLs, while I don't see ways to do the same in
OO, at least not for inheritance: there are too many useful type
relationships that cannot be captured using inheritance, and all
remedies that I have seen are too complicated.)

Just my 2c.
Jo

Mark Nicholls

unread,
Jun 3, 2004, 5:53:20 AM6/3/04
to

Yes and no....

SOA is primarily about communication between seperate system rather
than objects/components and thus the forces ar work are different...

Remember DCOM? or the problems associated with thick RDMS connections
loosing the server? or statefull Remoting?

I wrote a big long rant on our internal wiki about EAI (enterprise
application integration) and SOA pointing out exactly the same
observation i.e. SOA is functional in style because it needs to be
stateless. I could post it but its too big, too inflamatory, and
probably completely off track for what you're after.

The problem with statefull objects (in this context) is that there
needs to be a connection between between the reference to the object
and the object state itself and that that state needs to be maintained
between method invocations, this creates problems with respect to....

resilience - the reference exists in one system and the state exists
in another, while it is reasonable within a single application to
assume that because I have a reference there must be an valid
statefull object at the other end, this is a big assumption between
systems which may be on different machines on different networks in
different physical locations...network glitch and it all goes BOOM.

cost - because the connection between reference and statefull object
is crucial then often there needs to be a mechanism to make sure that
both ends of the connection are up and running i.e. pinging etc.

scalability - because state is maintained between method calls then if
I have 10,000 connections between my system and external systems I
need to maintain that state, even when noone is actually doing
anything.

The magic answer is get rid of the state and sell it under a fancy
banner i.e. SOA - its got the words oriented and architecture in it,
so most people wont notice it's in fact functional in style.

If your interested I can strongly recommend "enterprise integration
patterns" as a comlete end to end discussion as to the problems and
solutions in this area.

P.S.

It should also preferably be message based and asynchoronous, which
most out the box web service style things currently aren't.

Michael N. Christoff

unread,
Jun 3, 2004, 11:51:38 AM6/3/04
to

"Mark Nicholls" <Nichol...@mtvne.com> wrote in message
news:bdf4e330.04060...@posting.google.com...

How would one solve the following problem in a SOA: Start with N
distributed agents who communicate asynchronously by passing messages (ie:
in this case xml documents). Assume the network is reliable in the sense
that all sent messages are eventually recieved correctly and exactly once
but they may be delayed arbitrarily and possibly out of order. The N agents
are each initially given one input out of a (possibly infinite) set of
predefined inputs (ie: each is given a specific instance of an xml schema by
a user). After a finite amount of time, they must all agree on a single
output. This output must be one of the N inputs initially given to the
agents. An extension of this problem would be to require all agents to
output no more than k, 1 <= k < N, distinct outputs, all of which must,
again, be one of the initial inputs. No restriction is placed on the
connectivity of the network except that a single agent failure should not
disconnect the network.

Another problem: Same topology as above. In a finite amount of time they
must output the spanning tree of their network connectivity.

I suppose that one could consider each agent a port on an enterprise service
bus...? I'm sure this isn't a difficult problem (unless we demand a fault
tolerant system in which the agents always succesfully solve the problem
even in the case of, say, 1 agent being faulty in the sense that it may
permanently stop sending messages after a certain time).


Thanks,

Mike N. Christoff

Michael N. Christoff

unread,
Jun 3, 2004, 12:01:32 PM6/3/04
to

"Michael N. Christoff" <mchri...@sympatico.caREMOVETHIS> wrote in message
news:gQHvc.32702$Hn.10...@news20.bellglobal.com...

That should _a_ spanning tree, not _the_ spanning tree.

>
> I suppose that one could consider each agent a port on an enterprise
service
> bus...? I'm sure this isn't a difficult problem (unless we demand a fault
> tolerant system in which the agents always succesfully solve the problem
> even in the case of, say, 1 agent being faulty in the sense that it may
> permanently stop sending messages after a certain time).
>
>
> Thanks,
>
> Mike N. Christoff
>

By the way, to give these problems some context. They can have applications
in distributed database commit and dynamic network routing. Also, assume N
is quite large (ie: distributed database commit amongst, say, 3 agents in an
internal network is not very hard).

l8r, Mike N. Christoff

Topmind

unread,
Jun 3, 2004, 4:22:49 PM6/3/04
to
>
> > For the past decade and a half, the software industry mantra has been
> > OO. We have heard repeatedly that an object-oriented design is more
> > maintainable, more reusable and more resilient to changing
> > requirements. Now suddenly the air is abuzz with Service-oriented
> > Architecture. Object-orientation does not seem to be cool any more!
>
> It has been accepted for some time that there is no automatic way of
> making good software. No technique or methodology automagically generates
> maintainable, reusable and robust code.
>
> Why is OO good? It builds on well understood concepts from other
> techniques: modularity and loose coupling between modules.

Both these tend to be rather fuzzy concepts. One often finds
that there is no single one right way to group related things
because they often interact in multiple dimensions, and code
can only group (major) by one dimension at a time because text
is linear. Thus, the laws of physics prevent a single
one-size-fits-all grouping.

One way around this is to factor more of the info into
a database and away from code so that we can get the
views we need for the circumstances at hand. Our view
then becomes virtual instead of hard-coded into text code.
OO fans don't like this approach for some still undefined
reason. They like their static, hard-wired code grouping.

And "coupling" is not necessarily good or bad. Coupling is putting
your toothpaste and deoderant in the same bag so that you can move
them around as a unit, for example. If you fully decoupled them,
you would have to carry them around independently, and thus have
more things to keep track of. Coupling is
something to be managed, not
gotten rid of. Otherwise we would just have a huge soup of
tiny independent things that overwhelm us.

Databases help here again because the grouping is virtual,
as-needed. You can search for all red bottles across different
bags instead of go through each bag one at a time. Red-ness
and which-bag-ness are just different
perspectives (attributes) on the same things. Thus, we
can have virtual coupling by "baggativity" and by
color. We are not forced to find the One Right Perspective,
or the One Right Taxonomy because there is none.

However, more powerful abstraction such as this
may have some performance costs. Better abstraction often
requires more horse-power, and as machines get faster,
the text-file-centric approach will diminish I predict.
Things with hard-code structures like OO Visitor will
be laughed off the planet, and
put into the Goto Pasta Museum.

-T-
oop.ismad.com

Joachim Durchholz

unread,
Jun 3, 2004, 4:31:05 PM6/3/04
to
Michael N. Christoff wrote:
>
> How would one solve the following problem in a SOA: Start with N
> distributed agents who communicate asynchronously by passing messages (ie:
> in this case xml documents). Assume the network is reliable in the sense
> that all sent messages are eventually recieved correctly and exactly once
> but they may be delayed arbitrarily and possibly out of order. The N agents
> are each initially given one input out of a (possibly infinite) set of
> predefined inputs (ie: each is given a specific instance of an xml schema by
> a user). After a finite amount of time, they must all agree on a single
> output. This output must be one of the N inputs initially given to the
> agents. An extension of this problem would be to require all agents to
> output no more than k, 1 <= k < N, distinct outputs, all of which must,
> again, be one of the initial inputs. No restriction is placed on the
> connectivity of the network except that a single agent failure should not
> disconnect the network.
>
> Another problem: Same topology as above. In a finite amount of time they
> must output the spanning tree of their network connectivity.
>
> I suppose that one could consider each agent a port on an enterprise service
> bus...? I'm sure this isn't a difficult problem

Last time I looked (admittedly several months ago), problems of this
kind were hard. Most algorithms that I have seen for this kind of task
were O(N^2) or worse.
Replace "messages may be delayed by an arbitrary amount of time" with
"messages are guaranteed to arrive within some bounded time" and it's
far easier.

This is stuff for systems programming though, hard algorithmic work.
Stuff like SOA and OO are about organizing computations with known
solutions, so not about inventing algorithms, so I don't think that the
answers to your problem will help find out how good SOA is.

Just my 2c.
Jo

Michael N. Christoff

unread,
Jun 3, 2004, 5:00:04 PM6/3/04
to

"Joachim Durchholz" <j...@durchholz.org> wrote in message
news:c9o1qj$8n3$1...@news.oberberg.net...

Thanks for your answer. I would have conjectured how it could be solved
with SOA but refrained to avoid illuminating my lack of experience with SOA.
So would you say things like peer to peer distributed computing are outside
the scope of SOA? A major difference I notice between p2p and SOA is that
SOA typically assumes a MANY to FEW type of topology (ie: millions of
consumers and partners accessing your company's services), similar to client
server, but obviously a step above. I have heard of web services
choreography interface (WSCI) and it _seems_ like it may be useful in
allowing, at least limited, p2p-like functionality. In p2p you would
typically deal with FEW to FEW topologies (ie: so-called 'small-world
graphs'). However, I'll have to continue thinking about it.

l8r, Mike N. Christoff

Joachim Durchholz

unread,
Jun 3, 2004, 6:52:37 PM6/3/04
to
Michael N. Christoff wrote:
>
> So would you say things like peer to peer distributed computing are
> outside the scope of SOA?

I don't know enough about SoA to say for sure; the descriptions given in
this thread indicate it's something akin OO, or maybe Corba. Neither
category has any connection to network topology problems, all take the
network for granted and build on top of it, so I'm just assuming it's
the same for SoA.

Regards,
Jo

Robert C. Martin

unread,
Jun 3, 2004, 9:45:53 PM6/3/04
to
On 2 Jun 2004 16:14:11 -0700, use...@sta.samsung.com (Generic Usenet
Account) wrote:

Service Oriented Architecture is not a bad idea (although
communicating packets through the http port is an immensely stupid
idea). It is completely orthogonal to OO. SoA can (and almost
certainly will) be implemented in OO languages using OO designs (so
long as the programmers understand OO design). Moreover, services are
by their very nature polymorphic, so SoA is in some sense an extension
of OO.

Functional decomposition is not a bad idea, nor was it ever a bad
idea. Indeed, all object oriented designs are functionally
decomposed. OO just adds polymorphism and encapsulation to that
decomposition. There was a time, in the 90's, where it was
fashionable to criticize designs as being "functionally decomposed"
meaning anti-OO. However, the fashion was naive.


-----
Robert C. Martin (Uncle Bob)
Object Mentor Inc.
unclebob @ objectmentor . com
800-338-6716

"The aim of science is not to open the door to infinite wisdom,
but to set a limit to infinite error."
-- Bertolt Brecht, Life of Galileo

JXStern

unread,
Jun 3, 2004, 10:28:42 PM6/3/04
to
On 3 Jun 2004 02:53:20 -0700, Nichol...@mtvne.com (Mark Nicholls)
wrote:

>It should also preferably be message based and asynchoronous, which
>most out the box web service style things currently aren't.

What he said, also what RCM said.

Services, objects, messages, interfaces, ... mix and match.

In general, message-based styles tend to be more loosely coupled than
their traditional opponents, remote procedure call styles.

The service trend also adds something new to the mix, either standard
interfaces (eg, objects, messages, whatever), or else standard
meta-interfaces for discovering interfaces (and servers).

J.

Mark Nicholls

unread,
Jun 4, 2004, 3:52:42 AM6/4/04
to

To a degree I agree with the original post...SOA is not OO and in a
sense is by definition not stateful OO. Experience seems to show that
statefull OO for inter application communication is in general a bad
idea, especially synchronous and non local communication.

We can argue the toss whether stateless objects are in fact just a
list of functions i.e. a functional API - to me they are, and we've
been there - or at least similar.

I would design both systems and the infrastructure in a standard OO
manner, but the architecture itself is effectively a functional one.

Mark Nicholls

unread,
Jun 4, 2004, 4:01:42 AM6/4/04
to

I'm no SOA guru, I've read 1 book (that was very good) specifically
about messaging solutions and various pitfalls to statefull,
synchronous communication and simply regurgitated some of it with my
own prejedices laid on top.

My background is real time machine automation and I actually see
little difference sending a message down a serial cable to sending a
message down a message queue to an SOA interface.

Thus I see little difference between an SOA implementation, a
stateless object or a functional API.

I think the problem posed is a general algorithmic question and the
wife wants me to cut the hedge so I'm off.

Cristiano Sadun

unread,
Jun 4, 2004, 6:27:34 AM6/4/04
to
Joachim Durchholz <j...@durchholz.org> wrote in news:c9oa3u$bun$1
@news.oberberg.net:

> Michael N. Christoff wrote:
>>
>> So would you say things like peer to peer distributed computing are
>> outside the scope of SOA?
>
> I don't know enough about SoA to say for sure; the descriptions given in
> this thread indicate it's something akin OO, or maybe Corba.

For what I get, a SOA is any architecture where

- synchronous and asyncrhonous service
- publicly accessible registry of services
- uniform discovery protocol of services
- uniform description protocol of services
- uniform invocation protocol of services
- uniform security (autenthication and authorization) protocol for
invoking services

are used as central concepts in building a system.

Obiviously all this can be implemented with RPC, OO, Corba, message queues
or subjects/topics etc. Or even COBOL and a network stack if u want.

Certain technologies (notably webservices) simply promise to get you there
faster. Others (for example CORBA or message brokes) focused more on
different aspects but could (are) be used to implement SOAs.

Cristiano Sadun

unread,
Jun 4, 2004, 6:46:52 AM6/4/04
to
Nichol...@mtvne.com (Mark Nicholls) wrote in
news:bdf4e330.04060...@posting.google.com:

> To a degree I agree with the original post...SOA is not OO and in a
> sense is by definition not stateful OO.

You have a point here: objects "tend" to have a state and having their
behaviour depending on that state. In a sense, completely stateless
objects (as u say below, lists of functions packaged in a class) are sort
of special case - shouldn't be the norm.

However, I think of SOA and OO at two different levels: being service-
oriented is more an overall external property of a system - being object-
oriented is more an internal property of its architecture/design.

An OO system does not need to expose its functionalty as objects. For
example, lots of OO systems expose their functionalty via GUI menus and
dialogs, where the user picks up a specific function, fills in the
parameters (a dialog) and pushes "OK" (does the invocation). Obviously
the GUI is often *implemented* in objects - but the user sees what is
conceptually a function call (do this with these parameters). Command-
line based systems do that even more clearly.

Of course lots of other OO systems expose directly the objects they're
composed of - usually with a simple translation to an easy-to-use
denotation (text, XML, database rows, you name it). But doesn't need be.

A SOA for example could be implemented by an OO architecture centered on
a "Service" class.

> Experience seems to show that
> statefull OO for inter application communication is in general a bad
> idea, especially synchronous and non local communication.
>
> We can argue the toss whether stateless objects are in fact just a
> list of functions i.e. a functional API - to me they are, and we've
> been there - or at least similar.
>
> I would design both systems and the infrastructure in a standard OO
> manner, but the architecture itself is effectively a functional one.

Yep. Of course, after a while we may want to build super-systems :)
composed of other systems - and the "external", interface properties of
them become the internal plumbing of the super-system.

In that case, each individual system would either be modeled as a set of
functions, or a class be defined to - for example - coordinate the
execution of collaborating services. In that case, if some services could
be made "private" and the collaboration state hidden as well, we would
perhaps still have an OO system - with a similar degree of
"objectiveness" to OO systems that wrap around legacy procedural ones.

Chris F Clark

unread,
Jun 4, 2004, 11:04:52 AM6/4/04
to
Someone (as quoted by Topmind) wrote:
> Why is OO good? It builds on well understood concepts from other
> techniques: modularity and loose coupling between modules.

Topmind replied:


> Both these tend to be rather fuzzy concepts. One often finds
> that there is no single one right way to group related things
> because they often interact in multiple dimensions, and code
> can only group (major) by one dimension at a time because text
> is linear. Thus, the laws of physics prevent a single
> one-size-fits-all grouping.
>
> One way around this is to factor more of the info into
> a database and away from code so that we can get the
> views we need for the circumstances at hand. Our view
> then becomes virtual instead of hard-coded into text code.
> OO fans don't like this approach for some still undefined
> reason. They like their static, hard-wired code grouping.

OO is not necessarily about text and is also a fuzzy concept, with no
universally accepted definition. There are even OO systems that build
on databases with muliple views just like you propose--if fact, it
seems most Smalltalk systems are of that nature.

The OO system I use for compiler writing (Yacc++) in fact explicitly
has different forms of inheritance at different levels so that one can
factor at multiple levels, since the factoring at different levels is
likely to have a different hierarchical structure--that is one might
have one hierarchy representing the parsing structure, another
hierarchy representing the semantic structure, and a third hierarchy
representing implementation details, each using seperate inheritance
trees so that one can factor appropriately. As Topmind said,


> We are not forced to find the One Right Perspective,
> or the One Right Taxonomy because there is none.

The interesting thing (in terms of your point) is that all of these
separate hierarchies are expressed in text. Text itself is not the
problem. In fact linearity is not the problem. It is established
over and over again, that it is easy to write a transformation that
takes muliple dimensions and maps them onto an ordering in one
dimension, so that one can have the muplie views expressed in a linear
representation--all one needs is the inverse ampping to extract the
dimensions back out. As a result, C programers can cope with one
dimensional arrays, and functional programmers love their Currying,
and single inheritance language users can employ a pattern that
effectively gives them multiple dispatch.

Now, I have nothing against databases. Moreover, if your point is
that easy accesses to multiple views is a good thing, I won't argue
against that either. However, you will find that I tend to be rather
strongly opinioned that most any system is better if somewhere,
somehow one can conveniently translate the system into a linear
textual representation, manipulate that text, and regenerate the
modified non-linear model. That turns out to be a very powerful
idiom.

Topmind's final point:


> Things with hard-code structures like OO Visitor will be laughed off
> the planet, and put into the Goto Pasta Museum.

There is nothing wrong with the visitor pattern per se. In fact,
there are many wonderful tools (e.g. JJtree and JTB) that will
automatically generate the visitor pattern structure for one, and that
coupled with separate inheritance hierarchies for different levels of
abstraction is actually an excellent way of capturing some of those
multiple dimensions.

Finally, I think it is worth mentioning that "aspect oriented
programming" seems directly focused on the concept of adding a
dimension to a pre-existing programming structure that originally
neglected it.

Kind Regards,
-Chris

*****************************************************************************
Chris Clark Internet : com...@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------

Matthias Blume

unread,
Jun 4, 2004, 11:34:54 AM6/4/04
to
Ian Woods <news...@wuggyNOCAPS.org> writes:

> Why is OO good? It builds on well understood concepts from other
> techniques: modularity and loose coupling between modules. All good
> programming techniques which I've encountered are based on these two
> concepts.

The obvious logical fallacy here is that from "all X have property Y"
it does not follow that "if z has property Y then it is an X".

> OO is good because it applies these concepts well and adds
> sound guidelines and concepts which simplify the practical problems of
> reusing code and determining the responsibilities, ownership and
> interface of real modules.

This sounds more like a statement of faith. In fact, every single
point here is highly debatable.

> Inheritence, with these principals in mind, is simply one way of deriving
> a 'new' black-box module from an existing one. It's an example of reuse.

Obviously one cannot derive a new black box (in the way inheritance
does it) from an existing one if the existing one were really "black".

Matthias

Joachim Durchholz

unread,
Jun 4, 2004, 4:00:53 PM6/4/04
to
Chris F Clark wrote:
>
> There is nothing wrong with the visitor pattern per se.

Except that it prevents easy extension of one of the two type sets.

> In fact,
> there are many wonderful tools (e.g. JJtree and JTB) that will
> automatically generate the visitor pattern structure for one,

Nothing against these tools... however, whenever code generators come
into play, I keep thinking that compilers and libraries are tools as
well, and why doesn't the compiler provide the functionality that the
tools give us? Leaving me with the conclusion that the presence of a
generator tools highlights a deficit in the language. (This doesn't mean
the language is crap. It just means that there's room for improvement,
in the particular area addressed by the generator.)

Regards,
Jo

Michael N. Christoff

unread,
Jun 4, 2004, 6:38:27 PM6/4/04
to

"Matthias Blume" <fi...@my.address.elsewhere> wrote in message
news:m1u0xr8...@tti5.uchicago.edu...
> Ian Woods <news...@wuggyNOCAPS.org> writes:

>
> > Inheritence, with these principals in mind, is simply one way of
deriving
> > a 'new' black-box module from an existing one. It's an example of reuse.
>
> Obviously one cannot derive a new black box (in the way inheritance
> does it) from an existing one if the existing one were really "black".
>

Why not? To inherit from a class one does not (in general) need to know the
internals of the class they are inheriting from. Only the interface is
needed, and even black boxes have interfaces. Black box implies 'unknown
internal composition/implementation', it does not imply 'no interface to the
outside world', and it also does not imply a lack of knowledge of the
expected types of inputs and outputs the black box needs and produces.

l8r, Mike N. Christoff

Matthias Blume

unread,
Jun 4, 2004, 9:54:09 PM6/4/04
to
"Michael N. Christoff" <mchri...@sympatico.caREMOVETHIS> writes:

> "Matthias Blume" <fi...@my.address.elsewhere> wrote in message
> news:m1u0xr8...@tti5.uchicago.edu...
> > Ian Woods <news...@wuggyNOCAPS.org> writes:
>
> >
> > > Inheritence, with these principals in mind, is simply one way of
> deriving
> > > a 'new' black-box module from an existing one. It's an example of reuse.
> >
> > Obviously one cannot derive a new black box (in the way inheritance
> > does it) from an existing one if the existing one were really "black".
> >
>
> Why not? To inherit from a class one does not (in general) need to know the
> internals of the class they are inheriting from.

Unfortunately, in general this is wrong. Look up "open recursion" to
see what I mean.

> Only the interface is
> needed, and even black boxes have interfaces. Black box implies 'unknown
> internal composition/implementation', it does not imply 'no interface to the
> outside world', and it also does not imply a lack of knowledge of the
> expected types of inputs and outputs the black box needs and produces.

You are talking about abstract datatypes here. Unfortunately,
(implementation-)inheritance is not only not the same as abstraction,
it often even breaks it.

Cheers,
Matthias

Topmind

unread,
Jun 4, 2004, 10:31:48 PM6/4/04
to


But that is not what OO is about (although definitions are
all over the map). Anyhow, if you can treat
classes as data nodes, then you have a database of sorts,
which is closer to what I seek. However, it is a navigational
database, yet I think relational is more consistent,
disciplined, and generally superior to navigational.
Thus, if go that route, then do it right.


>
> Topmind's final point:
> > Things with hard-code structures like OO Visitor will be laughed off
> > the planet, and put into the Goto Pasta Museum.
>
> There is nothing wrong with the visitor pattern per se. In fact,
> there are many wonderful tools (e.g. JJtree and JTB) that will
> automatically generate the visitor pattern structure for one, and that
> coupled with separate inheritance hierarchies for different levels of
> abstraction is actually an excellent way of capturing some of those
> multiple dimensions.
>
> Finally, I think it is worth mentioning that "aspect oriented
> programming" seems directly focused on the concept of adding a
> dimension to a pre-existing programming structure that originally
> neglected it.

You may be interested in:

http://www.c2.com/cgi/wiki?CodeGenerationIsaDesignSmell

>
> Kind Regards,
> -Chris
>

Thanks for the feedback,
-T-

Joachim Durchholz

unread,
Jun 5, 2004, 2:28:04 AM6/5/04
to
Michael N. Christoff wrote:

> "Matthias Blume" <fi...@my.address.elsewhere> wrote:
>
>>Obviously one cannot derive a new black box (in the way inheritance
>>does it) from an existing one if the existing one were really "black".
>
> Why not?

The problem is not with inheritance per se, it's with overriding virtual
functions that may called from elsewhere in any of the ancestor classes:
you never quite know whether the routine you intend to override is
called for its code (in which case you cannot override it, or have to
override the calling methods as well - which can become quite merry if
any of these methods is nonvirtual/final), or called for its contract
(in which case overriding isn't just possible but actually required).
(Even worse problems can arise if call order issues are involved.)

You'd need information on the internal call structure of the superclass
to reliably override any routine, and *why* each routine is called - and
since this kind of information isn't captured within any OO language
that I know of, this pretty much means you need to have at least read
access to the source code of all ancestor classes.

> To inherit from a class one does not (in general) need to know the
> internals of the class they are inheriting from. Only the interface is
> needed,

This is enough if you're prepared to reimplement the entire class. Which
is OK in general, but must superclasses aren't designed for this kind of
reimplementation, since the functions needed to do that are often
considered "internal" by the superclass author and sealed against reuse
(i.e. marked private).
I hit that roadblock several times in my life, and didn't enjoy the
experience...

(Sorry for getting more and more off-topic.)

Regards,
Jo

Ian Woods

unread,
Jun 5, 2004, 6:01:57 AM6/5/04
to
Matthias Blume <fi...@my.address.elsewhere> wrote in
news:m1u0xr8...@tti5.uchicago.edu:

> Ian Woods <news...@wuggyNOCAPS.org> writes:
>
>> Why is OO good? It builds on well understood concepts from other
>> techniques: modularity and loose coupling between modules. All good
>> programming techniques which I've encountered are based on these two
>> concepts.
>
> The obvious logical fallacy here is that from "all X have property Y"
> it does not follow that "if z has property Y then it is an X".

Certainly, I didn't provide a sound argument to state that techniques
which promote modularity and loose coupling between modules. My logic
here was simply "If property X and Y is sufficient for a technique to be
good, and if Z has property X and Y then Z is good.".

All good techniques which I know of exhibit those two basic properties,
and all the bad technqiues don't. If there are some good tehcniques which
don't use liberal amounts of modularity and loose coupling, I'd like to
hear about them. (And the next question after this should most likely be
"Good for what?")

>> OO is good because it applies these concepts well and adds
>> sound guidelines and concepts which simplify the practical problems
>> of reusing code and determining the responsibilities, ownership and
>> interface of real modules.
>
> This sounds more like a statement of faith. In fact, every single
> point here is highly debatable.

Then debate them!



>> Inheritence, with these principals in mind, is simply one way of
>> deriving a 'new' black-box module from an existing one. It's an
>> example of reuse.
>
> Obviously one cannot derive a new black box (in the way inheritance
> does it) from an existing one if the existing one were really "black".
>
> Matthias

Sure you can, and I've done so on a number of occasions.

The typical OO language provides you with a black area (private), a grey
area (protected) and a white area (public). The interface is all nice and
public, the soft squishy underbelly which needs to be hidden is split
between the black and grey areas. It's often the case that the protected
area is most often used and the private area is only used whenever
necessary. This was a programmers decision, however, and nothing to do
directly with OO or OO inheritence.

There's been a number of occasions in OO software I've written where what
was required was two black box interfaces: one for 'users' of the box,
and one for 'children' of the box. OO languages provide this for me. What
they don't provide is the ability to have a box with two or more seperate
public interfaces as part of the language - this concept being somewhat
outside of the OO paradigm as far as I've seen.

Matthias Blume

unread,
Jun 5, 2004, 9:04:55 PM6/5/04
to
Ian Woods <news...@wuggyNOCAPS.org> writes:

> Matthias Blume <fi...@my.address.elsewhere> wrote in
> news:m1u0xr8...@tti5.uchicago.edu:
>
> > Ian Woods <news...@wuggyNOCAPS.org> writes:
> >
> >> Why is OO good? It builds on well understood concepts from other
> >> techniques: modularity and loose coupling between modules. All good
> >> programming techniques which I've encountered are based on these two
> >> concepts.
> >
> > The obvious logical fallacy here is that from "all X have property Y"
> > it does not follow that "if z has property Y then it is an X".
>
> Certainly, I didn't provide a sound argument to state that techniques
> which promote modularity and loose coupling between modules. My logic
> here was simply "If property X and Y is sufficient for a technique to be
> good, and if Z has property X and Y then Z is good.".

Of course, the properties in question, while probably necessary, are
not sufficient.

> >> OO is good because it applies these concepts well and adds
> >> sound guidelines and concepts which simplify the practical problems
> >> of reusing code and determining the responsibilities, ownership and
> >> interface of real modules.
> >
> > This sounds more like a statement of faith. In fact, every single
> > point here is highly debatable.
>
> Then debate them!

No, thank you. I had my share of flamewars without hope of
resolution. I have neither time nor energy for that.

> The typical OO language provides you with a black area (private), a grey
> area (protected) and a white area (public). The interface is all nice and
> public, the soft squishy underbelly which needs to be hidden is split
> between the black and grey areas. It's often the case that the protected
> area is most often used and the private area is only used whenever
> necessary. This was a programmers decision, however, and nothing to do
> directly with OO or OO inheritence.

If you made everything private (which is the only way of avoiding
those issues with open recursion in these "typical" languages), you
effectively prohibit overriding. Personally, I would find that a Good
Thing(tm), but I bet your average C++ programmer begs to differ. So
in practice we are stuck with "protected" -- which means open
recursion, and no black box. (I don't care whether you make a
distinction between "white" and "grey". Once it isn't "black", the
damage is already done.)

> There's been a number of occasions in OO software I've written where what
> was required was two black box interfaces: one for 'users' of the box,
> and one for 'children' of the box. OO languages provide this for me. What
> they don't provide is the ability to have a box with two or more seperate
> public interfaces as part of the language - this concept being somewhat
> outside of the OO paradigm as far as I've seen.

There is at least one such language, but it is still being developed.
Incidentally, it leaves issues such as "public" vs. "private" to the
language's module system (where it, IMO, belongs), as opposed to the
type- and class-system.

Matthias

Michael N. Christoff

unread,
Jun 6, 2004, 1:49:07 PM6/6/04
to

"Joachim Durchholz" <j...@durchholz.org> wrote in message
news:2id7fvF...@uni-berlin.de...

I agree that interfaces are often inadequate to describe an object's full
contract (ie: sequencing issues) and docs must play a vital role. But it
seems like (at least in single-inheritance languages) it should not be too
hard to avoid most of these pitfalls by using things like factories and
encapsulation (ie: do not make internal use of overridable methods).
However, I'm not an expert. Truthfully, I find that I rarely use
implementaion inheritance at all anymore.

l8r, Mike N. Christoff

Joachim Durchholz

unread,
Jun 6, 2004, 5:59:49 PM6/6/04
to
Michael N. Christoff wrote:
> I agree that interfaces are often inadequate to describe an object's
> full contract (ie: sequencing issues) and docs must play a vital
> role. But it seems like (at least in single-inheritance languages)
> it should not be too hard to avoid most of these pitfalls by using
> things like factories and encapsulation (ie: do not make internal use
> of overridable methods).

Good strategy.

> Truthfully, I find that I rarely use implementaion inheritance at all
> anymore.

This seems to be a conclusion that may draw.

(It's also the reason why I'm posting from comp.lang.functional, not
anymore from a OO newsgroup.)

Regards,
Jo

Mark Nicholls

unread,
Jun 7, 2004, 5:44:31 AM6/7/04
to
>
> > To a degree I agree with the original post...SOA is not OO and in a
> > sense is by definition not stateful OO.
>
> You have a point here: objects "tend" to have a state and having their
> behaviour depending on that state. In a sense, completely stateless
> objects (as u say below, lists of functions packaged in a class) are sort
> of special case - shouldn't be the norm.

Yes, after doing 5 minutes reading around, SOA can be stateful...it
just isn't usually, so I was wrong, SOA by def is not
stateless....which now mildly confuses me.

>
> However, I think of SOA and OO at two different levels: being service-
> oriented is more an overall external property of a system - being object-
> oriented is more an internal property of its architecture/design.

I must admit now to being a little confused from seing how SOA differs
from OO in any really meaningful way. If it's simply the encapsulation
and publishing of 'services' rather than 'objects', I can't see any
real difference with that and publishing command style objects i.e. if
'services' aren't OO then commands aren't - (OK there's all the other
stuff about having a lookup service and uniform security, but that
doesn't really seem anything new or special).

>
> An OO system does not need to expose its functionalty as objects. For
> example, lots of OO systems expose their functionalty via GUI menus and
> dialogs, where the user picks up a specific function, fills in the
> parameters (a dialog) and pushes "OK" (does the invocation). Obviously
> the GUI is often *implemented* in objects - but the user sees what is
> conceptually a function call (do this with these parameters). Command-
> line based systems do that even more clearly.
>
> Of course lots of other OO systems expose directly the objects they're
> composed of - usually with a simple translation to an easy-to-use
> denotation (text, XML, database rows, you name it). But doesn't need be.
>
> A SOA for example could be implemented by an OO architecture centered on
> a "Service" class.
>

A genuine question...what makes it an object a service rather than
not?

To me any class/object exposed as an external interface to a system
exposing methods which are effectively 'services' to/on that system.

You've posted.....

- synchronous and asyncrhonous service
- publicly accessible registry of services
- uniform discovery protocol of services
- uniform description protocol of services
- uniform invocation protocol of services
- uniform security (autenthication and authorization) protocol for
invoking services

on another sub thread, which I completely accept, but does this mean
that things like COM+/CORBA are SOA's as they provide these services
already.

Then the emporer seems to have even less clothes than I first,
cyniclly, thought, he is truly naked.

> > Experience seems to show that
> > statefull OO for inter application communication is in general a bad
> > idea, especially synchronous and non local communication.
> >
> > We can argue the toss whether stateless objects are in fact just a
> > list of functions i.e. a functional API - to me they are, and we've
> > been there - or at least similar.
> >
> > I would design both systems and the infrastructure in a standard OO
> > manner, but the architecture itself is effectively a functional one.
>
> Yep. Of course, after a while we may want to build super-systems :)
> composed of other systems - and the "external", interface properties of
> them become the internal plumbing of the super-system.
>
> In that case, each individual system would either be modeled as a set of
> functions, or a class be defined to - for example - coordinate the
> execution of collaborating services. In that case, if some services could
> be made "private" and the collaboration state hidden as well, we would
> perhaps still have an OO system - with a similar degree of
> "objectiveness" to OO systems that wrap around legacy procedural ones.

I don't understand this last bit.

Cristiano Sadun

unread,
Jun 7, 2004, 10:08:17 AM6/7/04
to

>> A SOA for example could be implemented by an OO architecture centered


>> on a "Service" class.
>>
>
> A genuine question...what makes it an object a service rather than
> not?
>
> To me any class/object exposed as an external interface to a system
> exposing methods which are effectively 'services' to/on that system.

Yes, I often use the same wording myself - "an object exposes services to
its client code". The only difference I can see with regard to SOA is
that, in the latter, you have all the paraphernalia which *explicitly*
makes easy to discover and invoke such services and for them to be
interoperable, to handle their lifecycle explicitly, and the common
situation is (should be) the asynchoronous request/state polling rather
the synchornous RPC. It is, I'd say, a matter of emphasis rather than
structural distinction. "service" is the main (and only) metaphor in SOA,
while with objects you have a richer modeling vocabulary and tools. Also
"service" at object level tends to be lower-level or at least more fine
grained than the ones in a SOA. Not that they have to - but they tend to.

Let me make some concrete examples of what I mean:

a) In C++, there's no doubt you can create objects (in the OO sense, with
polymorphism, information hiding etc). C++ supports, therefore, OO.
However, there's no mechanism for publishing objects outside the
immediate runtime address space (heap/stack); there's no standard way to
invoke them outside code on the same platform (i.e. I can't load and run
a C++ binary object which happens to reside in an object module produced
by a win32 compiler on another o/s); no standard way of make them
"active"; no notion of "quality of service"; etc. Still, it's possible to
build a SOA with C++, only it isn't the most immediate of things.

b) Java as a language offers more immediate binary interoperability, a
bit of security, a bit of runtime access (via the classloading
mechanism... but not particularly emphasized as a way to publish services
- for example, once u've loaded a class in the system classoader, it
stays loaded until the JVM is shutdown); as a platform, you get a bit
more - RMI is Java-centric CORBA. So, is Java a SOA? No, but can support
it.

c) DCOM (or what's the name of the week) and CORBA are built over certain
programming languages and start offering explicitly "services". While
DCOM can also do other stuff (is a way to achieve binary-compatible
packaging of whatever piece of win32 code or resource, not just objects)
CORBA, in particular, is what I figure the nearest thing already there
that allows to implement a SOA... I don't add "easily" since that
adjective near to CORBA doesn't come natural. :)

That's some of the why I tend to see SOA as at an higher abstraction
level than object-orientation. OO refers mainly to source code
structuring and interdependence; SOA is any architecture that's based on
the concept of higher-level "service"s and allows whomever to know which
services are there and to invoke them - independently from source code.

> on another sub thread, which I completely accept, but does this mean
> that things like COM+/CORBA are SOA's as they provide these services
> already.

Indeed they do. CORBA especially - but then I'm definitely not a
DCOM/COM+ expert.

>
> Then the emporer seems to have even less clothes than I first,
> cyniclly, thought, he is truly naked.

It is. Marketing always needs a new short word. :)

>> Yep. Of course, after a while we may want to build super-systems :)
>> composed of other systems - and the "external", interface properties
>> of them become the internal plumbing of the super-system.
>>
>> In that case, each individual system would either be modeled as a set
>> of functions, or a class be defined to - for example - coordinate the
>> execution of collaborating services. In that case, if some services
>> could be made "private" and the collaboration state hidden as well,
>> we would perhaps still have an OO system - with a similar degree of
>> "objectiveness" to OO systems that wrap around legacy procedural
>> ones.
>
> I don't understand this last bit.

My fault. What I meant is that, initially, we build separate systems -
and we build them with OO techniques; their internal plumbing is,
logically, in terms of message exchanges among objects. Say, an order
system and a credit-check system - each having its own internal and
separate model for "person", "credit", "card" etc.

Then, we decide that some of the functionality of that system be exposed
as service. For example "order a toy X" and "verify credit for Mr. Y"
etc.

Then, tomorrow, we decide to build an integrated system which is based on
the collaboration of the existing systems. Say, a system which does both
credit check and toy ordering in one shot if the credit allows it -
enabling a single "pay toy X" functionality.

For this latter system, we may chose to integrate the object models
(difficult) or to coordinate the exposed (procedural) services.

In that latter case, the services become the plumbing (i.e. the internal
way of doing things) for the integrated system.

Cristiano Sadun

unread,
Jun 7, 2004, 10:19:02 AM6/7/04
to
"Michael N. Christoff" <mchri...@sympatico.caREMOVETHIS> wrote in
news:IT6wc.131631$tb4.4...@news20.bellglobal.com:

> To inherit from a class one does not (in general) need to know the
> internals of the class they are inheriting from.

Alas, that's true only in theory - or better, from a purely functional
perspective. In practice, performance and footprint considerations makes it
ofen necessary to know the internals - and perhaps to change them.

Joachim Durchholz

unread,
Jun 7, 2004, 10:19:19 AM6/7/04
to
Cristiano Sadun wrote:
> Nichol...@mtvne.com (Mark Nicholls) wrote

>
>>>A SOA for example could be implemented by an OO architecture centered
>>>on a "Service" class.
>>
>>A genuine question...what makes it an object a service rather than
>>not?
>>
>>To me any class/object exposed as an external interface to a system
>>exposing methods which are effectively 'services' to/on that system.
>
> Yes, I often use the same wording myself - "an object exposes services to
> its client code". The only difference I can see with regard to SOA is
> that, in the latter, you have all the paraphernalia which *explicitly*
> makes easy to discover and invoke such services and for them to be
> interoperable, to handle their lifecycle explicitly, and the common
> situation is (should be) the asynchoronous request/state polling rather
> the synchornous RPC.

OO plus a good does of introspection...

> a) In C++, there's no doubt you can create objects (in the OO sense, with
> polymorphism, information hiding etc). C++ supports, therefore, OO.
> However, there's no mechanism for publishing objects outside the
> immediate runtime address space (heap/stack);

... plus builtin marshalling/unmarshalling.

Anything new?
;-)

(Dropping out.)

Regards,
Jo

Chris F Clark

unread,
Jun 7, 2004, 12:17:01 PM6/7/04
to
Chris F Clark wrote:
C> There is nothing wrong with the visitor pattern per se.

Joachim Durchholz replied:
J> Except that it prevents easy extension of one of the two type sets.

That's why tools to generate the pattern are important. The pattern
is a pain to generate and maintain by hand, although it resolves a
different pain. With the right tools, both pains can be mitigated.

C> In fact,
C> there are many wonderful tools (e.g. JJtree and JTB) that will
C> automatically generate the visitor pattern structure for one,

J> Nothing against these tools... however, whenever code generators come
J> into play, I keep thinking that compilers and libraries are tools as
J> well, and why doesn't the compiler provide the functionality that the
J> tools give us? Leaving me with the conclusion that the presence of a
J> generator tools highlights a deficit in the language. (This doesn't
J> mean the language is crap. It just means that there's room for
J> improvement, in the particular area addressed by the generator.)

I think language designs are inherently flawed in this area. One
cannot design a language that is perfect *for everything* (and
attempting to do so, invariably results in a language that isn't as
good for anything)--PERL being a cannonical example, while it has many
wonderful characteristics, it is not as good in some ways, as less
"ambitious" languages. (And I'm not trying to suggest that I could
have made a better set of tradefoffs than those in PERL, just that for
many things PERL is not the language of first choice for me, precisely
due to some of the factors that make it good for other tasks.)

As a result, I am a big fan of "domain specific" or "little"
languages. Often, it is much better to build another tool that adds
another layer than trying to patch the underlying tool to be "ideal"
for the case at hand. One exception to that rule occurs when the
layer needs to be integrated, then it is better to extend the
underlying tool. Whether one wants loose or tight coupling is an
issue even at the language design level.

This goes back to my point about text. One needs to be able to find
the right point to inject the additional layer, sometimes it is at the
head of the tool chain list, sometimes its at the tail. And the only
way to insert conveniently anywhere in the list is if each stage has
an easily manipulated representation.

Working, as I now do, in the chip making (EDA) industry, it is
interesting to see how "right" (and sometimes "wrong") they get that.
Almost all EDA tools use easily manipulable formats (both as input and
as output) and most of those formats are either defacto or dejure
standards. That allows one to have "tool chains" or "flows" that use
a variety of tools from different vendors to get the desired result.
Most EDA flows are not perfect due to the compounding of the flaws in
the individual tools in the chain, but they are better than one
integrated tool would have been, especially across the myriad of
different users.

Best regards,

Chris F Clark

unread,
Jun 7, 2004, 12:45:06 PM6/7/04
to
Most of the interaction snipped, befor TopMind put in a pointer to the
following web page:

> http://www.c2.com/cgi/wiki?CodeGenerationIsaDesignSmell

The pages seem to indicate that one is counting the output lines and
worse intending to maintain the output lines. Any good use of
automatic code generation is one where one only customizes the input.
I don't count how many lines of code are generated by my tools. I
don't want to edit that output either.

The proper use of code generation is to allow one to program at a
higher level (the level of the input to the code generator) which
should be substantially smaller than the output.

However, I do want the output lines to be in a manipulable format
(e.g. text), because sometimes one needs to do something with the
output that the origian code generator author didn't intend. For
example, we wanted to use a hand written memory manager for certain
objects that were automatically generated. As such, it was important
that we could take the automatically generated output and run it
through a tool that could autmatically apply the correct edits to the
generated objects to insert the apropriate memory mnager calls.
However, we did not and do not want to insert the calls by hand. we
don't hand edit the output to implement things (well, sometimes we do
as a prototyping method, but we alwasy fold those changes back into
the input).

To the point, most hand written parsers ad full of flaws due to ad hoc
inconstincies--most automatically generated parsers do not suffer from
the same flaws, but they would if one hand edited the output of the
parser generator. Programming at the higher level--the grammar is
more rigorous and results in fewer flaws. One does not generate code
to edit it. That would be a mistake.

That does not mean that their are not cutpoints that are only visible
in the generated code, and one may need to manipulate the output of a
generator. Just tyhat one doesn't generally do that by hand.

Mark Nicholls

unread,
Jun 7, 2004, 1:55:26 PM6/7/04
to
> >
> > Then the emporer seems to have even less clothes than I first,
> > cyniclly, thought, he is truly naked.
>
> It is. Marketing always needs a new short word. :)
>

I stand corrected then and I must work on my cynicism skills, I
obviously becoming lazy about it in my old ade.

Joachim Durchholz

unread,
Jun 7, 2004, 2:12:51 PM6/7/04
to
Chris F Clark wrote:
> I think language designs are inherently flawed in this area. One
> cannot design a language that is perfect *for everything* (and
> attempting to do so, invariably results in a language that isn't as
> good for anything)--PERL being a cannonical example, while it has
> many wonderful characteristics, it is not as good in some ways, as
> less "ambitious" languages.

There are design trade-offs involved, yes.
However, I don't think that it's impossible to design a "perfect"
language. It's just very, very hard... Perl being the canonical example
of trading too much of some things for still not enough of others ;-)

For example, FPLs don't need a Visitor pattern. Or, more precisely, it's
possible to make Visitor into a set of functions that do all the
footwork for you, and applying the pattern means calling that function
in a single place.
(The FPL would be statically typed. Otherwise, setting up Visitor would
be trivial...)

> (And I'm not trying to suggest that I could have made a better set of
> tradefoffs than those in PERL, just that for many things PERL is not
> the language of first choice for me, precisely due to some of the
> factors that make it good for other tasks.)

There are always design trade-offs like those you have in mind. The
trick is to find a way to transform the language so that the trade-offs
stop being trade-offs.
It's hard - otherwise we'd already have the perfect language. It's also
very difficult to explore a novel way of doing things. Functional
languages, for example, used to have a lot of trade-offs (in terms of
e.g. efficiency, and real-world interaction), and it took at least a
decade to find satisfactory answers to the issues.
Today, I'd say that "strict" functional languages are at a level that
the functional paradigm is ready for "production use". People should go
and look what idioms work best, how to set up and manage large
libraries, explore what kinds of language support are useful for these.
I.e. making FPLs ready for mainstream use isn't rocket science anymore.

> As a result, I am a big fan of "domain specific" or "little"
> languages.

FPLs excel at writing "embedded languages" (a synonym of
"domain-specific language"). IOW you write in that "little language"
without even realizing that the idioms and control structures are really
just library functions.
No need to write a tool on top of the language, the compiler already
does what's needed...

Regards,
Jo

Chris F Clark

unread,
Jun 7, 2004, 3:20:28 PM6/7/04
to
In an FPL, the Visitor pattern (and other embeddings) might be easily
implementable as only a series special function definitions that build
the correct framework. I'm not that well versed yet. However, as of
yet I do not have the luxury of always working in an FPL (nor even
doing so regularly--i.e. as part of my job), so I still need generator
tools to get the pattern conveniently into the imperative framework in
which I live.

Joachim Durchholz said:
> No need to write a tool on top of the language, the compiler already
> does what's needed...

Which is part of the motivation for learning FP....

The only thing I worry about is "efficiency", with a tool, if I need
to implement a transitive closure over something to determine whether
something can be done or not, I can easily run the closure at compile
time and not worry about it's run time cost. Since most of the
"macro" packages I've seen for embedding little languages seen to do
so naively (e.g. recursive descent parsing rather than LR), I worry
that expressing the some closure needs to be computed at compile time,
is intrinsically hard to do. Actually, that's not just an efficiency
concern for me also, sometimes the closure is needed to detect
specification errors (e.g. ambiguous grammars)--I want to be informed
in advance that I have written a poor specification rather than have
some unsuspecting user get the message that I failed to do my job and
their input fell into my hole.

-Chris

Chris F Clark

unread,
Jun 7, 2004, 3:28:50 PM6/7/04
to
Most of the interaction snipped, befor TopMind put in a pointer to the
following web page:

> http://www.c2.com/cgi/wiki?CodeGenerationIsaDesignSmell

Note, if one reads and chases far enough, one sees most of my
arguments covered by one author or another. The only point that isn't
covered is the stuff about manipulable output, and perhaps I didn't
wander far enough. It is also clear from those pages, that my
definition of code generation is "active code generation" in their
terms.

Apologies,
-Chris

Joachim Durchholz

unread,
Jun 8, 2004, 7:07:47 AM6/8/04
to
Chris F Clark wrote:
>
> Joachim Durchholz said:
>> No need to write a tool on top of the language, the compiler
>> already does what's needed...
>
> Which is part of the motivation for learning FP....

Just like myself :-)

> The only thing I worry about is "efficiency", with a tool, if I need
> to implement a transitive closure over something to determine whether
> something can be done or not, I can easily run the closure at
> compile time and not worry about it's run time cost. Since most of
> the "macro" packages I've seen for embedding little languages seen to
> do so naively (e.g. recursive descent parsing rather than LR), I
> worry that expressing the some closure needs to be computed at
> compile time, is intrinsically hard to do.

I'm not sure about the current state of things on the FPL side.
My conjecture is that, since FPLs encourage not using side effects, it's
possible to have the compiler precompute all constant expressions.

In other words, if you need an LR parser, you write down the syntax
rules in a domain-specific language/library, and the compiler will run
the code that generates the transition tables.

I'm not sure whether this kind of scheme is currently supported by any
of the more mainstream FPLs. It may well be that no special support is
required - FPL compilers tend to do a great deal of inlining and other
precomputation steps, so you may find that computing the closure is
quite fast :-)
(Then again, you may find differently.)

> Actually, that's not just an efficiency concern for me also,
> sometimes the closure is needed to detect specification errors (e.g.
> ambiguous grammars)--I want to be informed in advance that I have
> written a poor specification rather than have some unsuspecting user
> get the message that I failed to do my job and their input fell into
> my hole.

Again, I don't know whether current-day FPLs do this.
In principle, there's nothing that can't be done here - all the compiler
has to do is to determine that evaluating the expression that generates
the tables would raise an exception, and generates code that raises this
exception directly.
Either you'd have to write a simple test program that just accesses the
table. It would be better if the language had assertion support; in that
case, this kind of test can be encoded directly.

Regards,
Jo

Programmer Dude

unread,
Jun 8, 2004, 9:22:50 AM6/8/04
to
Mark Nicholls writes:

> The problem with statefull objects (in this context)...
>
> resilience -
> cost -
> scalability -
>
> The magic answer is get rid of the state and sell it under a fancy
> banner i.e. SOA - its got the words oriented and architecture in it,
> so most people wont notice it's in fact functional in style.

I assume you're being wry in that last paragraph! (-:

Maybe an important point is that when the costs of a stateful connection
can be managed, accepted or ignored (for example, scalability might be
an issue you can ignore, and resilience might be managable with a good
network). As always in this craft, "It Depends!" (-:

WHEN the cost is acceptable (for example, it's *zero* within a given
program) statefulness is a hugely helpful model.

Stateless transaction processing is fine for MANY things, but there are
MANY other things that are modal. That is, they consist of a series of
steps in a required order (you have to open a file before you can read
or write on it). As such, most times you NEED statefulness.

The big issue with any web transaction consisting of more than one page
is "how the heck to you impose statefulness on http"? (I'm not saying
there aren't many fine answers...just that it's the big question you
do *have* to solve to design any multi-page web thing.)

--
|_ CJSonnack <Ch...@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|_______________________|

Programmer Dude

unread,
Jun 8, 2004, 9:22:48 AM6/8/04
to
Joachim Durchholz writes:

> I don't know enough about SoA to say for sure; the descriptions given in

> this thread indicate it's something akin OO, or maybe Corba. Neither
___________________________________________^^
(did you mean "COM"?)

> category has any connection to network topology problems, all take the
> network for granted and build on top of it, so I'm just assuming it's
> the same for SoA.

Seems a safe bet with "Architecture" in the name.

Been a fascinating discussion, and one or the other of you has managed
to mention each point I'd thought of to mention so far...

Leaving me with little to contribute. :-(

M'be I'll just summarize what seems to be the common theme here:

1. SOA is just another organizational technique for us. In fact,
it's just a new name for something that's been around computing
for a while, AND has been around humans for longer. It's a
pretty obvious provider/consumer model

2. SOA probably isn't a fair comparison with OOP (and I submit that if
you do translate one in terms of the other, Services ARE objects,
and Service Requests are Messages ala Smalltalk....or: Objects ARE
Services--self contained blackboxes). SOA sounds an "applet-level"
organizational technique, OOP is really about writing code.

3. OOP isn't going away. First, because it, too, is just a new name
for an old model. Second, it IS an ideal model for many situations.
So is SOA. And AOP. And FP. And PP.

Maybe here's a new point:

As technology evolves, the models for organizing that technology
successfully also change. When transportation is perilous and/or
expensive, de-centralization is a more successful model.

But this means each "client" must spend resources managing and
storing their inventory (be it bananas, bits or state). When the
cost of transportation drops--that is, when the *infrastructure*
becomes a viable commodity--it becomes more efficient to centralize.

Here the risk is in the three distinct, hugely decoupled componants
involved (that is, provider-transportation-consumer). Each of these
three is a separately-managed physical resource, and the middle one
is usually comprised of *many* separately-managed resources.

Failure of any is a certain risk that distributed models (regardless
of organization) *must* consider.


And that's just one dimension. Another is the whether transportation
is transaction based--that is, stateless, each transaction is a
complete unit--or whether transportation is a "connection" wherein
both sides contribute, manage and sychronize resources.

Another dimension is provider/consumer mapping. Few-to-many sounds
like the Service model. Many-to-many is P2P. Many-to-few? Probably
more for smaller scale situations with a few consumers choosing from
a variety of consumers.

I donno, whatever. Point is, different goals, different solutions.

Programmer Dude

unread,
Jun 8, 2004, 9:22:52 AM6/8/04
to
Generic Usenet Account writes:

> When I look at services, I tend to look at them in functional
> terms AND NOT object terms.

But aren't they closer to objects than functions? Aren't they
self-contained, stand-alone units that service a variety of
requests? Compare that to a function which is a single "verb"
that may, or may not, be parameterized.

OOPLs such as Smalltalk are *VERY* similar to the SOA model!
And, perhaps interestingly, perhaps coincidentally, Smalltalk
is notorious as a "pure" OOPL.

Programmer Dude

unread,
Jun 8, 2004, 9:23:01 AM6/8/04
to
Topmind writes:

> And "coupling" is not necessarily good or bad. Coupling is putting
> your toothpaste and deoderant in the same bag so that you can move
> them around as a unit, for example.

I would call that binding, not coupling. The toothpaste and deoderant
are NOT coupled to each other in any way. They are BOUND together by
and outside agency.

> Databases help here again because the grouping is virtual,
> as-needed.

The EAI software I'm learning (and already supporting) in my new job
is interesting. It's basically an enormously complex series of
layers around a database. It starts with an bottom abstraction layer
that models the physical database. A middle layer provides business
logic and the top layer is presentation. By that time, you can bind
diverse data together in almost any fashion you choose.

> However, more powerful abstraction such as this
> may have some performance costs. Better abstraction often
> requires more horse-power, and as machines get faster,
> the text-file-centric approach will diminish I predict.


> Things with hard-code structures like OO Visitor will
> be laughed off the planet, and
> put into the Goto Pasta Museum.

I don't think so. I think they'll continue to live down in the
basement layers driving all that abstraction.

Rene de Visser

unread,
Jun 8, 2004, 10:29:48 AM6/8/04
to
"Joachim Durchholz" <j...@durchholz.org> wrote in message
news:ca46me$587$1...@news.oberberg.net...

possible to have the compiler precompute all constant expressions.
>
> In other words, if you need an LR parser, you write down the syntax
> rules in a domain-specific language/library, and the compiler will run
> the code that generates the transition tables.
>
This is what I had thought as well.

Though I'm a bit disturbed that the parser for GHC isn't defined in Haskell.

Its defined in a parser language which is then used to generate Haskell
code.

Which is then compiled and linked in with GHC.

This seems to contradict the idea that you can do this.

Does anyone know why the parser for GHC is not directly defined in Haskell?

Rene.


Joachim Durchholz

unread,
Jun 8, 2004, 12:05:38 PM6/8/04
to
Programmer Dude wrote:
> Joachim Durchholz writes:
>
>> I don't know enough about SoA to say for sure; the descriptions
>> given in this thread indicate it's something akin OO, or maybe
> ___________________________________________________^^

> (did you mean "COM"?)

I meant OO.
SoA sounded like a way to do architectures.

(I *still* don't understand what's new or interesting about it, but then...)

Regards,
Jo

Joachim Durchholz

unread,
Jun 8, 2004, 12:20:34 PM6/8/04
to
Programmer Dude wrote:
>
> WHEN the cost is acceptable (for example, it's *zero* within a given
> program) statefulness is a hugely helpful model.

In the functional community, the cost of state is usually considered
nonzero in the vast majority contexts, including programming locally.

Example: Code becomes far, far more flexible if you know it depends on
its parameters, and its parameters only, and if you also know that the
only effect that it can have is to return a value or to throw an exception.

Example 2: Aliasing (shared data) becomes a non-issue. Mutating any data
has always been making me wonder what other might have linked to that
data (hence be affected by the change). Since the the set of objects
linking to a given object is a nonlocal property, combining state and
the ability to freely create references together are unmodular.
Since you can create a reference to everything (at least in C/C++/Java),
the only option is to work statelessly, i.e. to create a copy of the
stateful object before modifying it, "just in case" - losing most of
those efficiency advantages that in-place modifications offer.
(This effect happens only in large software. I think that's one of the
reasons why bloatware is soo slow: as soon as programmers don't know all
uses of some piece of data, they have to copy it over and over again.
Reviewing a program restructuring for speed, from this perspective, is
just a case of data analysis to determine which of the copies are
actually superfluous...)

Example 3: You can drop all those tricky-to-define differences between
equality and identity.

> Stateless transaction processing is fine for MANY things, but there are
> MANY other things that are modal. That is, they consist of a series of
> steps in a required order (you have to open a file before you can read
> or write on it). As such, most times you NEED statefulness.

You need it whenever you interact with the outside world. It's stateful
after all - devices have state.
The point of functional programming is to avoid state wherever the
outside world doesn't require it.

> The big issue with any web transaction consisting of more than one page
> is "how the heck to you impose statefulness on http"? (I'm not saying
> there aren't many fine answers...just that it's the big question you
> do *have* to solve to design any multi-page web thing.)

Hey, HTTP *is* stateless (at least conceptually). And this has many
advantages, among them the ability to go back and review any page
without talking to the server, browsing many pages in parallel, etc.

I always swear at those braindead JavaScript sites that force me into
using just a single page at a time, don't allow me to go back via my
browser, don't allow me to go back and double-check some information
while I'm preparing payment.

Sure, a web shop has some important state, e.g. whether the customer has
committed to actually buying the stuff in his cart. It's just that a
whole lot of state is simply superfluous and should be avoided.

Regards,
Jo

Programmer Dude

unread,
Jun 9, 2004, 9:56:25 AM6/9/04
to
Joachim Durchholz writes:

> You'd need information on the internal call structure of the superclass
> to reliably override any routine, and *why* each routine is called - and
> since this kind of information isn't captured within any OO language
> that I know of, this pretty much means you need to have at least read
> access to the source code of all ancestor classes.

To the extent that this is true (and I agree it is often true), what
does that imply about OOP (insofar as OOP is about black boxes)?

Perhaps it is more about implementation inheritance than about OOP,
per se. As Michael responds to you, I also find my class libraries
are very broad and very shallow. Typically, only the most basic
types seem (to me) to make very good supers.

I've also been missing C++ interface inheritance feature. :-\

Joachim Durchholz

unread,
Jun 9, 2004, 11:02:52 AM6/9/04
to
Programmer Dude wrote:
> Joachim Durchholz writes:
>
>>You'd need information on the internal call structure of the superclass
>>to reliably override any routine, and *why* each routine is called - and
>>since this kind of information isn't captured within any OO language
>>that I know of, this pretty much means you need to have at least read
>>access to the source code of all ancestor classes.
>
> To the extent that this is true (and I agree it is often true), what
> does that imply about OOP (insofar as OOP is about black boxes)?
>
> Perhaps it is more about implementation inheritance than about OOP,
> per se.

Fully agreed. Client classes (those that call and don't inherit) are
encapsulated off very nicely.

OOP isn't just about black boxes - the idea of encapsulating a data type
together with the functions that work on it is generally termed
"object-based". Object-"oriented" means the addition of inheritance and
dynamic dispatch.

Personally, I'm for object-based, not object-oriented; implementation
inheritance is simply too simplicistic to capture all type relationships
that are important in practice, so some other mechanism should be in
place (something like parametric types or templates, plus dependent
types, plus the necessary glue to make the mix pleasant to use).

Haskell's type classes get quit near to my ideals :-)

Regards,
Jo

Mark Alexander Wotton

unread,
Jun 9, 2004, 6:58:35 PM6/9/04
to
On Tue, 8 Jun 2004 16:29:48 +0200, Rene de Visser posted:

Historical reasons, I think. There are robust and fast parser combinator
libraries for Haskell like Parsec now, so it could be switched over if
the developers wanted to...

(There's even a haskell-src package which lets you parse haskell source
in-language, so you needn't write the grammar yourself.)

mrak

--
realise your life was only bait for a bigger fish
-- aesop rock

Marco Dorantes

unread,
Jun 12, 2004, 12:38:01 PM6/12/04
to
Perhaps these could help to clarify:

SOA implies that OO is dead?
http://blogs.msdn.com/marcod/archive/2004/06/07/150420.aspx

Re-positioning of original intent, purposes and scope of OO among SOA benefits
http://blogs.msdn.com/marcod/archive/2004/06/10/152789.aspx

Best regards,

Programmer Dude

unread,
Jun 14, 2004, 12:29:30 PM6/14/04
to
Cristiano Sadun writes:

>> that things like COM+/CORBA are SOA's as they provide these
>> services already.
>
> Indeed they do. CORBA especially - but then I'm definitely
> not a DCOM/COM+ expert.

I make no claims to expertise, but even plain COM is very SOA-ish.
It has a way you can request it's functionality, for e.g.

Kirk Knoernschild

unread,
Jun 17, 2004, 9:51:47 AM6/17/04
to
I found the following article interesting - not so much for it's
discussion on modeling, but because it breaks down SOA, BPM, EA, and
OO (whew!).

http://www-106.ibm.com/developerworks/library/ws-soad1/

Kirk Knoernschild |
Senior Consultant/Instructor | www.kirkk.com
TeamSoft, Inc. | www.extensiblejava.com
Training, Mentoring, Consulting | www.teamsoftinc.com

use...@sta.samsung.com (Generic Usenet Account) wrote in message news:<90e5135.04060...@posting.google.com>...
> For the past decade and a half, the software industry mantra has been
> OO. We have heard repeatedly that an object-oriented design is more
> maintainable, more reusable and more resilient to changing
> requirements. Now suddenly the air is abuzz with Service-oriented
> Architecture. Object-orientation does not seem to be cool any more!
>
> When I take a closer look at SoA, it seems a lot closer to functional
> design than object-oriented design. When I look at services, I tend
> to look at them in functional terms AND NOT object terms. Whatever
> happened to those oft-repeated protestations that functional
> decomposition is bad and object-orientation is good?
>
> Am I missing something, or is the pendulum swinging back towards
> functional design? Whatever happened to those neat concepts like
> inheritance and polymorphism?
>
> Bhat

I spy

unread,
Jun 22, 2004, 5:59:03 AM6/22/04
to

"Joachim Durchholz" <j...@durchholz.org> wrote in message
news:ca78r7$dfj$1...@news.oberberg.net...
How would you implement something like the Decorator pattern without
inheritance?
(WindowWithScrollbar, WindowWithBorder, etc all need to be Windows and be
passable to any client that was expecting a Window)

Real type inheritance (which no language really supports with the possible
exception of Eiifel) doesn't introduce any coupling that wasn't already
there. ie if I inherit Square off Rectangle then its because a Square *is* a
rectangle. Provided I limit what I mean by inheritance to inheriting the
contract of the parent (and not the implementation - and this is where it
would be nice if Java supported actual types and not phony structures like
interfaces that have no semantics), then I see no problem

cheers
-sri

> Regards,
> Jo


Ketil Malde

unread,
Jun 22, 2004, 7:49:26 AM6/22/04
to
"I spy" <s_ned...@yahoo.com> writes:

>> Haskell's type classes get quit near to my ideals :-)

> How would you implement something like the Decorator pattern without
> inheritance?
> (WindowWithScrollbar, WindowWithBorder, etc all need to be Windows and be
> passable to any client that was expecting a Window)

If you want to have functions that work on all kinds of windows,
i.e. polymorphism, you could do

-- first define what defines these things
class Window a where
close :: a -> ...
move :: ...

class (Window a) => WindowWithScrollBar a where
scrollUp :: a -> ...
scrollDown :: ...

Now, any instance of WindowWithScrollBar has to be an instance of
Window also. So you can write

draw :: Window a => a -> IO ...
draw my_window = ...move...close... -- can also take a WWSB, of course

This is using (interface) inheritance, so it may not be an answer your
question?

-kzm
--
If I haven't seen further, it is by standing in the footprints of giants

Joachim Durchholz

unread,
Jun 22, 2004, 8:01:45 AM6/22/04
to
I spy wrote:
>
> How would you implement something like the Decorator pattern without
> inheritance?
> (WindowWithScrollbar, WindowWithBorder, etc all need to be Windows and be
> passable to any client that was expecting a Window)

I create a set of functions for each object (tagged with record field
names for efficient access). One function is for drawing the thing, one
is for intersection testing (e.g. to test whether the mouse cursor is on
it), one is for determining the reaction to a mouse click or keyboard
input, etc. etc.
I may even go so far as to build a new intersection testing function
whenever the window is moved or resized.
There is a separate set of functions for each window. Sure, they share
most of their code; after all, these functions were created by taking a
template function and instantiating it with some fixed values for some
of their parameters. (FP implementations make good use of this kind of
function creation to get the whole process efficient. The relevant
techniques have characteristics that are quite similar to those of
dynamic dispatch in OO languages: horribly inefficient when done
naively, but decent enough if you know the tricks of the trade.)

Now when I want to create a list of things that can be moved, I don't
place the entire objects in it. I simply make a list of move-the-window
functions - actually I can place any kind of function in it that has the
right signature. Since functions are data in an FPL, they also have a
type; the functions for the example list would have a signature like

Real delta_x, Real delta_y -> List<<Canvas_Action>>

The advantage is: you don't have to inherit from a common "CanvasItem"
superclass that may be polluting your namespace. All you have to do is
to implement a set of functions that do what you want. And if you don't
need a moveable window, you don't even have to provide a dummy
implementation :-)

> Real type inheritance (which no language really supports with the possible
> exception of Eiifel) doesn't introduce any coupling that wasn't already
> there.

... and Eiffel has type holes because it's overambitious with real type
inheritance :-(

> ie if I inherit Square off Rectangle then its because a Square *is* a
> rectangle.

Only if Rectangles are immutable.
If they are mutable, the procedure
scale (x_factor, y_factor: REAL)
doesn't have a meaningful semantics in Square. You are forced to either
conclude that neither type is a subtype of the other, to violate the
Liskov Substitution Principle, or to accept that you work only with
immutable data.

Which brings us full circle back to functional languages where
mutability is a less-used (sometimes even neglected) tool.

Regards,
Jo

I spy

unread,
Jun 23, 2004, 1:48:01 PM6/23/04
to

"Joachim Durchholz" <j...@durchholz.org> wrote in message
news:cb9701$4fd$1...@news.oberberg.net...

> I spy wrote:
> >
> > How would you implement something like the Decorator pattern without
> > inheritance?
> > (WindowWithScrollbar, WindowWithBorder, etc all need to be Windows and
be
> > passable to any client that was expecting a Window)
>
> I create a set of functions for each object (tagged with record field
> names for efficient access). One function is for drawing the thing, one
> is for intersection testing (e.g. to test whether the mouse cursor is on
> it), one is for determining the reaction to a mouse click or keyboard
> input, etc. etc.
> I may even go so far as to build a new intersection testing function
> whenever the window is moved or resized.
> There is a separate set of functions for each window. Sure, they share
> most of their code; after all, these functions were created by taking a
> template function and instantiating it with some fixed values for some
> of their parameters. (FP implementations make good use of this kind of
> function creation to get the whole process efficient. The relevant
> techniques have characteristics that are quite similar to those of
> dynamic dispatch in OO languages: horribly inefficient when done
> naively, but decent enough if you know the tricks of the trade.)
I am somewhat familiar with the techniques, having tried to emulate OO in a
Lisp like language I once had the misfortune of using several years ago. The
key problem as you rightly point out is simulating dynamic dispatch or
virtual functions. I don't really buy the roll-your-own approach. Its tough
enough writing good code without having to write your own language support.
You could make the same argument that I could create my own stack frames and
while loops in assembly language.

> Now when I want to create a list of things that can be moved, I don't
> place the entire objects in it. I simply make a list of move-the-window
> functions - actually I can place any kind of function in it that has the
> right signature. Since functions are data in an FPL, they also have a
> type; the functions for the example list would have a signature like
>
> Real delta_x, Real delta_y -> List<<Canvas_Action>>
>
> The advantage is: you don't have to inherit from a common "CanvasItem"
> superclass that may be polluting your namespace. All you have to do is
> to implement a set of functions that do what you want. And if you don't
> need a moveable window, you don't even have to provide a dummy
> implementation :-)

I am not sure what you mean by "polluting the namespace"

> > Real type inheritance (which no language really supports with the
possible
> > exception of Eiifel) doesn't introduce any coupling that wasn't already
> > there.
>
> ... and Eiffel has type holes because it's overambitious with real type
> inheritance :-(
>
> > ie if I inherit Square off Rectangle then its because a Square *is* a
> > rectangle.
>
> Only if Rectangles are immutable.
> If they are mutable, the procedure
> scale (x_factor, y_factor: REAL)
> doesn't have a meaningful semantics in Square. You are forced to either
> conclude that neither type is a subtype of the other, to violate the
> Liskov Substitution Principle, or to accept that you work only with
> immutable data.

I am unfortunately too familiar with the is-a-square-a-rectangle discussions
that draggged on ad nauseum on comp.object 7 or 8 years back. Mutable
atructures do indeed complicate the problem so perhaps I should have been
careful and said *immutable*. Anyway this is getting OT. The point I am
addressing is that to say inheritance introduces coupling and is therefore
bad is misleading, since it ignores the coupling already present that a good
inheritance structure simply makes use of.

> Which brings us full circle back to functional languages where
> mutability is a less-used (sometimes even neglected) tool.

not a bad thing, in my opinion. Mutability is the source of many bugs

> Regards,
> Jo


I spy

unread,
Jun 23, 2004, 1:57:40 PM6/23/04
to

"Ketil Malde" <ke...@ii.uib.no> wrote in message
news:egsmcno...@havengel.ii.uib.no...
It seems to me you've only defined type classes and not the actual types.
That is you would still need

instance Window SomeWindowType where ...
instance WindowWithScrollBar SomeWindowWithScrollBarType where ...

but unf. an instance of SomeWindowType (ie an actual window) is not an
instance of SomeWindowWithScrollBarType so you're still stuck

cheers
-sri

I spy

unread,
Jun 23, 2004, 2:03:59 PM6/23/04
to
While we're at it, I am puzzled by the following statement in the Haskell-98
Tutorial, under Comparisons to Other Languages:

" The class methods defined by a Haskell class correspond to virtual
functions in a C++ class.
Each instance of a class provides its own definition for each method; class
defaults correspond

to default definitions for a virtual function in the base class."

Virtual functions in C++ support the case where the type of something cannot
be statically determined and therefore need dynamic binding. Since types in
Haskell are statically inferred, I don't see this is a valid comparison.

cheers
-sri

"Joachim Durchholz" <j...@durchholz.org> wrote in message

news:cb9701$4fd$1...@news.oberberg.net...

John Atwood

unread,
Jun 23, 2004, 2:46:32 PM6/23/04
to
In article <2jtukmF...@uni-berlin.de>, I spy <s_ned...@yahoo.com> wrote:
< snip stuff about Haskell type classes>

>
>but unf. an instance of SomeWindowType (ie an actual window) is not an
>instance of SomeWindowWithScrollBarType so you're still stuck

A more complete presentation is given in
"Structuring Graphical Paradigms in TkGofer"
http://citeseer.ist.psu.edu/claessen97structuring.html

and see wxHaskell for a up-t-date, working GUI library along those lines:
http://wxhaskell.sourceforge.net/


John

Joachim Durchholz

unread,
Jun 23, 2004, 4:38:25 PM6/23/04
to
I spy wrote:

> "Joachim Durchholz" <j...@durchholz.org> wrote:
>
> I am somewhat familiar with the techniques, having tried to emulate
> OO in a Lisp like language I once had the misfortune of using several
> years ago.

The technique I was proposing does *not* emulate OO. The functions are
handed around independently of the objects that they operate on - in
fact the function is created in the first place by placing the object in
the function's parameter list, creating a new function of one less
parameter.
I.e. the objects are wrapped in functions, not the other way round.

> The key problem as you rightly point out is simulating dynamic
> dispatch or virtual functions. I don't really buy the roll-your-own
> approach. Its tough enough writing good code without having to write
> your own language support.

It's no roll-your-own OO (though that can be done if you really want).

>> The advantage is: you don't have to inherit from a common

>> "CanvasItem" superclass that may be polluting your namespace. [...]


>
> I am not sure what you mean by "polluting the namespace"

If I inherit the CanvasItem class, my new subclass automatically
contains all the stuff that was declared in the superclass, whether I
want it or not.
If the superclass is revised, it may acquire new machinery and hence new
names. Any subclass that happens to use the same name must be rewritten.

Regards,
Jo

Ketil Malde

unread,
Jun 24, 2004, 3:35:26 AM6/24/04
to
"I spy" <s_ned...@yahoo.com> writes:

> That is you would still need

> instance Window SomeWindowType where ...
> instance WindowWithScrollBar SomeWindowWithScrollBarType where ...

Yes.

> but unf. an instance of SomeWindowType (ie an actual window) is not an
> instance of SomeWindowWithScrollBarType so you're still stuck

Uh, I don't think a follow you here. Two concrete data types cannot
be 'instances' of each other. If you declare T to be an instance
of Window, you can perform window operations on it. If you declare it
to also be an instance of WindowWSB, you can do additional scroll bar
operations on it.

Types T1 and T2 both declared to be instances of a class don't need to
have any other relationship with each other, they can just be accessed
through the same interface, defined in the class.

Andreas Rossberg

unread,
Jun 24, 2004, 5:31:25 AM6/24/04
to
I spy wrote:
> While we're at it, I am puzzled by the following statement in the Haskell-98
> Tutorial, under Comparisons to Other Languages:
>
> " The class methods defined by a Haskell class correspond to virtual
> functions in a C++ class.
> Each instance of a class provides its own definition for each method; class
> defaults correspond
>
> to default definitions for a virtual function in the base class."
>
> Virtual functions in C++ support the case where the type of something cannot
> be statically determined and therefore need dynamic binding. Since types in
> Haskell are statically inferred, I don't see this is a valid comparison.

Types can be polymorphic in Haskell. How a polymorphic method
application is resolved depends on how the polymorphic type will be
instantiated. In general, you cannot derive all instantiations
statically (unlike C++ templates).

Cheers,

- Andreas

--
Andreas Rossberg, ross...@ps.uni-sb.de

Let's get rid of those possible thingies! -- TB

Dirk Thierbach

unread,
Jun 24, 2004, 6:56:20 AM6/24/04
to
I spy <s_ned...@yahoo.com> wrote:
> While we're at it, I am puzzled by the following statement in the
> Haskell-98 Tutorial, under Comparisons to Other Languages:

> "The class methods defined by a Haskell class correspond to virtual
> functions in a C++ class. Each instance of a class provides its own
> definition for each method; class defaults correspond to default
> definitions for a virtual function in the base class."

> Virtual functions in C++ support the case where the type of
> something cannot be statically determined and therefore need dynamic
> binding. Since types in Haskell are statically inferred, I don't see
> this is a valid comparison.

The *types* are statically inferred, but the *instances* can be chosen
by dynamic binding.

A somewhat artificial example:

class Example a where
what :: a -> String

data T1 = MakeT1

data T2 = MakeT2

instance Example T1 where
what _ = "foo"

instance Example T2 where
what _ = "bar"

doit :: Example a => a -> String
doit x = "what returns: " ++ what x

Now if you call "doit MakeT1", you get "what returns: foo". If you
call "doit MakeT2", you get "what returns: bar". Exactly the same
situation as for a virtual method "what" with classes T1 and T2 with
constructors MakeT1 and MakeT2. The only difference (in this respect)
is that the OO notion of a class is split into two parts: The "type of
the class" as the type class Example, and the "method definitions of
the class" as the instances.

So it *is* a valid comparison.

- Dirk

[Removed comp.programming and comp.sources.d from f'up]

I spy

unread,
Jun 24, 2004, 10:32:38 AM6/24/04
to

"Dirk Thierbach" <dthie...@gmx.de> wrote in message
news:kjoqq1-...@ID-7776.user.uni-berlin.de...
You missed my point. I was asking about "virtual functions" and not
inherited methods. My C++ is somewhat rusty as I haven't used it in years,
so I could be wrong here (pl correct me if I am) but as I recall, you don't
need virtual functions if you can statically resolve the binding. In the
example you give, I can do exactly that - MakeT1 returns a T1 instance, and
MakeT2 returns a T2 instance - there's no ambiguity about which function to
invoke. A virtual function is only required if I I had real inheritance (say
a common base type T from which T1 and T2 derive) and the instance I pass
could be a T1 or a T2 and which it is won't be known until runtime. As
Haskell doesn't support type inheritance this problem cannot arise in
Haskell. So, unless I am very much mistaken about C++ virtual functions,
this still looks like an incorrect comparison

cheers
-sri


I spy

unread,
Jun 24, 2004, 10:46:56 AM6/24/04
to

"Ketil Malde" <ke...@ii.uib.no> wrote in message
news:egbrj9j...@havengel.ii.uib.no...

> "I spy" <s_ned...@yahoo.com> writes:
>
> > That is you would still need
>
> > instance Window SomeWindowType where ...
> > instance WindowWithScrollBar SomeWindowWithScrollBarType where ...
>
> Yes.
>
> > but unf. an instance of SomeWindowType (ie an actual window) is not an
> > instance of SomeWindowWithScrollBarType so you're still stuck
>
> Uh, I don't think a follow you here. Two concrete data types cannot
> be 'instances' of each other. If you declare T to be an instance
> of Window, you can perform window operations on it. If you declare it
> to also be an instance of WindowWSB, you can do additional scroll bar
> operations on it.
I wasn't suggesting that the types be instances of each other (!). I was
talking about actual window objects. As an example consider
simpleWindow::SomeWindowType and scrollWindow::SomeWindowWithScrollBarType.
Haskell doesn't allow scrollWindow (ie the actual window object, not the
type!) to be an instance of SomeWindowType. But that is exactly the magic
that allows the Decorator pattern to work. In an OO language, a scrollWindow
*is a* SomeWindowType object. I can pass scrollWindow around everywhere
(subject to LSP) that a SomeWindowType object (such as simpleWindow) is
expected, therefore no existing client code is broken. My point is that
without subtype polymorphism + dynamic binding I don't see how you can do
this (straighforwardly) in Haskell.

cheers
-sri

I spy

unread,
Jun 24, 2004, 11:08:16 AM6/24/04
to

"Joachim Durchholz" <j...@durchholz.org> wrote in message
news:cbcpku$i7m$1...@news.oberberg.net...

> I spy wrote:
> > "Joachim Durchholz" <j...@durchholz.org> wrote:
> >
> > I am somewhat familiar with the techniques, having tried to emulate
> > OO in a Lisp like language I once had the misfortune of using several
> > years ago.
>
> The technique I was proposing does *not* emulate OO. The functions are
> handed around independently of the objects that they operate on - in
> fact the function is created in the first place by placing the object in
> the function's parameter list, creating a new function of one less
> parameter.
> I.e. the objects are wrapped in functions, not the other way round.
Perhaps I'm not following you. Let me see if I understand: You have several
types T1...Tn which let says might inherit from one another in an OO
language. In an OO language, there would also be m methods for each type (to
keep things simple assume each type has the same named methods).
Corresponding to this You define m*n curried functions. At run time you have
a list of partially assigned functions (where one of the parameters
represents the "object"), and you can invoke each in turn, which knows what
to do since it's carrying around its object argument with it. If my
understanding is correct...how is this different from roll your own OO? True
you don't have to do a v-table lookup, but that's because you've essentially
done your own v-table assignment at the time you bound the object to its
associated function! In addition, you can't take advantage of inheritance so
you really are forced to define all m*n functions. Yes, it does the job but
it hardly looks like a win to me.


> > The key problem as you rightly point out is simulating dynamic
> > dispatch or virtual functions. I don't really buy the roll-your-own
> > approach. Its tough enough writing good code without having to write
> > your own language support.
>
> It's no roll-your-own OO (though that can be done if you really want).
>
> >> The advantage is: you don't have to inherit from a common
> >> "CanvasItem" superclass that may be polluting your namespace. [...]
> >
> > I am not sure what you mean by "polluting the namespace"
>
> If I inherit the CanvasItem class, my new subclass automatically
> contains all the stuff that was declared in the superclass, whether I
> want it or not.

Well that goes back to the issue of whether your inheritance hierarchy was
appropriate to start with. Again think of the WindowWithScrollBar class. If
I add stuff to the Window base class, then yes I would want
WindowWithScrollBar to reflect that too. If not, then add it privately.

> If the superclass is revised, it may acquire new machinery and hence new
> names. Any subclass that happens to use the same name must be rewritten.

That's what refactoring tools are for...

cheers

> Regards,
> Jo


Dirk Thierbach

unread,
Jun 24, 2004, 12:05:25 PM6/24/04
to
I spy <s_ned...@yahoo.com> wrote:
>> The *types* are statically inferred, but the *instances* can be chosen
>> by dynamic binding.
>>
>> A somewhat artificial example:
>>
>> class Example a where
>> what :: a -> String
>>
>> data T1 = MakeT1
>>
>> data T2 = MakeT2
>>
>> instance Example T1 where
>> what _ = "foo"
>>
>> instance Example T2 where
>> what _ = "bar"
>>
>> doit :: Example a => a -> String
>> doit x = "what returns: " ++ what x
>>

> You missed my point.

I don't think so :-)

> I was asking about "virtual functions" and not inherited methods.

Yes. But the difference between virtual and non-virtual functions
is only visible when doing inheritance in C++.

> My C++ is somewhat rusty as I haven't used it in years, so I could
> be wrong here (pl correct me if I am) but as I recall, you don't
> need virtual functions if you can statically resolve the binding.

But you cannot statically resolve the binding in the above the example.
The corresponding C++ code is (ignoring stupid errors -- I did't compile
it; and printing directly in doit, because it's simpler):

class Example {
virtual char* what () { return "abstract"; }
};

class T1 : Example {
virtual char* what () { return "foo"; }
};

class T2 : Example {
virtual char* what () { return "bar"; }
};

void doit (Example x)
{
cout << "what returns: " << x.what ();
}

Note that Example now becomes an abstract base class (in Haskell,
only the type is needed, the actual implementation is not interesting);
and T1 and T2 both get their own types (which are not needed, because
they are the same as Example).

If you drop the virtual keyword, doit will return "abstract" instead
of "foo" or "bar".

> In the example you give, I can do exactly that - MakeT1 returns a T1
> instance, and MakeT2 returns a T2 instance - there's no ambiguity
> about which function to invoke.

But this is not known statically inside doit. That's the whole point
of the exercise.

> A virtual function is only required if I I had real inheritance (say
> a common base type T from which T1 and T2 derive)

It's not "real" inheritance, but something similar. See above.

> So, unless I am very much mistaken about C++ virtual functions,
> this still looks like an incorrect comparison

It seems you are mistaken :-)

You can also look at it from the implementation viewpoint: In OOP,
there's a virtual method table (VMT) that gets passed as an extra
parameter. In Haskell, you pass an extra parameter called "Dictionary".
Both contain the pointers to the actual methods. Same idea in both
cases.

- Dirk


Andreas Rossberg

unread,
Jun 24, 2004, 1:09:58 PM6/24/04
to
I spy wrote:
>
> I wasn't suggesting that the types be instances of each other (!). I was
> talking about actual window objects. As an example consider
> simpleWindow::SomeWindowType and scrollWindow::SomeWindowWithScrollBarType.
> Haskell doesn't allow scrollWindow (ie the actual window object, not the
> type!) to be an instance of SomeWindowType. But that is exactly the magic
> that allows the Decorator pattern to work. In an OO language, a scrollWindow
> *is a* SomeWindowType object. I can pass scrollWindow around everywhere
> (subject to LSP) that a SomeWindowType object (such as simpleWindow) is
> expected, therefore no existing client code is broken. My point is that
> without subtype polymorphism + dynamic binding I don't see how you can do
> this (straighforwardly) in Haskell.

Mh, existential types seem straightforward enough in Haskell and are
actually more powerful than subtype polymorphism (see e.g. Kim Bruce'
book on "Foundations of Object-Oriented Languages", where he actually
proposes dropping subtyping in favor of existentials, in the disguise of
"hash types").

John Atwood

unread,
Jun 24, 2004, 12:26:24 PM6/24/04
to
In article <2k07r5F...@uni-berlin.de>, I spy <s_ned...@yahoo.com> wrote:
>type!) to be an instance of SomeWindowType. But that is exactly the magic
>that allows the Decorator pattern to work. In an OO language, a scrollWindow
>*is a* SomeWindowType object. I can pass scrollWindow around everywhere
>(subject to LSP) that a SomeWindowType object (such as simpleWindow) is
>expected, therefore no existing client code is broken. My point is that
>without subtype polymorphism + dynamic binding I don't see how you can do
>this (straighforwardly) in Haskell.


It's done with parametric polymorphism with class constraints. Sorta like
mixins...


John

Joachim Durchholz

unread,
Jun 24, 2004, 9:23:53 PM6/24/04
to
I spy wrote:
> "Joachim Durchholz" <j...@durchholz.org> wrote:
>
> Perhaps I'm not following you. Let me see if I understand: You have
> several types T1...Tn which let says might inherit from one another
> in an OO language. In an OO language, there would also be m methods
> for each type (to keep things simple assume each type has the same
> named methods).

Agreed until here.

> Corresponding to this You define m*n curried functions.

No, not at all. I'd define n curried functions - I'm not interested in
doing the other (m-1) functions to fill just a single list.

> At run time you have a list of partially assigned functions

Just for the record:
These are called "curried functions".
It's also a simple case of closures.

> (where one of the parameters represents the "object"), and you can
> invoke each in turn, which knows what to do since it's carrying
> around its object argument with it. If my understanding is
> correct...how is this different from roll your own OO?

Because that parameter isn't very "object-like" anymore.
The list element can't invoke arbitrary functions on it. This can be a
Good Thing or a Bad Thing, depending on the situation :-) [see below for
some ramifications]

> True you don't have to do a v-table lookup, but that's because you've
> essentially done your own v-table assignment at the time you bound
> the object to its associated function!

You're correct about the v-table lookup - basically, everybody is
dispatching somewhere. Pascal programmers do it using "case", OO
programmers do it using dynamic dispatch, functional programmers do it
using currying.
The above situation is different, however. If you will, the list
contains degenerate vtables - each of them can dispatch only to one
single function.

Now, if having a list of just one function is too limited, you can
construct records of curried functions. And such a record is indeed
functionally identical to a vtable - here it's indeed a roll-your-own
vtable.

There's one important difference though: in the OO world, these tables
are generated at compile time. In the FP world, they are generated at
hoc, at run time; this means you compose your sets of functions as the
situation mandates, not according to the whims of the class designers.

This is deeper than one might think at first. For example, when
implementing subclasses, you're often forced to implement tons of
nitty-gritty little functions that aren't needed for the concrete
application you have in mind, but you have to implement them anyway
because the parent class requires them.
In the FP world, I just write those functions that I actually need.

> In addition, you can't take advantage of inheritance so you really
> are forced to define all m*n functions. Yes, it does the job but it
> hardly looks like a win to me.

Typical FPLs don't even have inheritance, they use different mechanisms.
They are most similar to C++'s templates (but better).
I.e. you take an existing implementation, instantiate a few parameters,
and you almost have what you want.
It's more disciplined in a sense (because you can't wilfully override
functions with something subtly different), yet flexible enough.

>>>> The advantage is: you don't have to inherit from a common
>>>> "CanvasItem" superclass that may be polluting your namespace.
>>>> [...]
>>>
>>> I am not sure what you mean by "polluting the namespace"
>>
>> If I inherit the CanvasItem class, my new subclass automatically
>> contains all the stuff that was declared in the superclass, whether
>> I want it or not.
>
> Well that goes back to the issue of whether your inheritance
> hierarchy was appropriate to start with. Again think of the
> WindowWithScrollBar class. If I add stuff to the Window base class,
> then yes I would want WindowWithScrollBar to reflect that too. If
> not, then add it privately.

No, I didn't mean that.
Say the Window class contains a GdiHandle member. It's private since
it's doing very, very crufty internal stuff, so the subclass can't even
access it.
Yet when the subclass declares a GdiHandle member, it has a name clash.

Particularly classes like Window tend to have far more than 100 members.
Now that's a full namespace!
(Been there, done that - I recently spent the three years working on a
OO GUI library, which weighed in at a six-digit LoC count...)

>> If the superclass is revised, it may acquire new machinery and
>> hence new names. Any subclass that happens to use the same name
>> must be rewritten.
>
> That's what refactoring tools are for...

If refactoring tools were a solution, then namespace pollution wouldn't
be a problem.
Specifically, things get more difficult if you're the author of the
subclass and the superclass is maintained (and changed) by somebody else
- particularly if you get a new version of the library with all-new and
all-changed internals.
Things get even more difficult if you're the author of the superclass
and forced to stick with the names you already used because most of the
subclass authors don't have refactoring tools to begin with.

(BTW I haven't heard of a *working* refactoring tools for C++ *g* - no
surprise, the C++ semantics is very tricky, and any tool that does code
modification at a large scale must "know" about the ins and outs of
every detail.
Of course, that's just C++, not OO in general.)

Regards,
Jo

Ketil Malde

unread,
Jun 25, 2004, 3:09:00 AM6/25/04
to
"I spy" <s_ned...@yahoo.com> writes:

> I wasn't suggesting that the types be instances of each other (!). I was
> talking about actual window objects. As an example consider
> simpleWindow::SomeWindowType and scrollWindow::SomeWindowWithScrollBarType.
> Haskell doesn't allow scrollWindow (ie the actual window object, not the
> type!) to be an instance of SomeWindowType.

No, the two types (data structures) are different.
But they will both be members of the Window class, which defines the
operations on a window. Thus all window manipulation functions should
be polymorphic, with a Window class constraint.

I.e. having types like:

win_op :: (Window a) => a -> ...

which will work for both types.

So, to use OOish lingo, instead of having classes SWT and SWWSBT
inheriting from it directly, we have classes W and WWSB as abstract
base classes defining the interfaces, WWSB inherits from W. SWT
inherits from W, and SWWSBT inheriting from WWSB.

The classes are decoupled from the implementations, but you get the
same effect - at least as far as I can tell. I think I've even seen
advice recommending this kind of design in OO.

The only 'problem' are heterogenous collections, which you can do by
existentials (promising you'll only use operations from the Window
class), or by wrapping the different window types.

I spy

unread,
Jun 25, 2004, 1:16:35 PM6/25/04
to

"Dirk Thierbach" <dthie...@gmx.de> wrote in message
news:5narq1-...@ID-7776.user.uni-berlin.de...
Right but I claim your C++ code is doing over and above what the
corresponding Haskell can do. See below

> > In the example you give, I can do exactly that - MakeT1 returns a T1
> > instance, and MakeT2 returns a T2 instance - there's no ambiguity
> > about which function to invoke.
>
> But this is not known statically inside doit. That's the whole point
> of the exercise.

I see what you're doing but in fact your use of overloading is gratuitous.
At the time you call doit, you (as in the client code) know what type of
argument you're calling it on - that's the only way Haskell can possibly
resolve it. That is, the example would have worked equally well if you had
doitT1 and and a doitT2, calling whichever was appropriate.

> > A virtual function is only required if I I had real inheritance (say
> > a common base type T from which T1 and T2 derive)
>
> It's not "real" inheritance, but something similar. See above.
>
> > So, unless I am very much mistaken about C++ virtual functions,
> > this still looks like an incorrect comparison
>
> It seems you are mistaken :-)

Um, perhaps not. In your C++ code as you have it, the argument to doit could
be either a T1 or a T2 (for example you're iterating over a list of
Examples, eacho of which could be a T1 or a T2), *and it is not possible for
the compiler to determine which*. Therefore the use of virtual there is
understandable and indeed without it, would not be correctly dispatched. But
in cases where I do know whether or not I have a T1 or a T2 coming in, use
of virtual is superflous. This is the correct analogue of the Haskell
situation.

cheers
-sri


I spy

unread,
Jun 25, 2004, 1:47:56 PM6/25/04
to

"Joachim Durchholz" <j...@durchholz.org> wrote in message
news:cbfuo7$rgp$1...@news.oberberg.net...

> I spy wrote:
> > "Joachim Durchholz" <j...@durchholz.org> wrote:
> >
> > Perhaps I'm not following you. Let me see if I understand: You have
> > several types T1...Tn which let says might inherit from one another
> > in an OO language. In an OO language, there would also be m methods
> > for each type (to keep things simple assume each type has the same
> > named methods).
>
> Agreed until here.
>
> > Corresponding to this You define m*n curried functions.
>
> No, not at all. I'd define n curried functions - I'm not interested in
> doing the other (m-1) functions to fill just a single list.
OK, I was taking the general case, supposing the other functions were of
interest - which is typical. Its not *often* you'll be using just one
function out of a class. But OK, let's just assume you're only interested in
the one function. And I see below that you consider the multi function case.

> > At run time you have a list of partially assigned functions
>
> Just for the record:
> These are called "curried functions".
> It's also a simple case of closures.

I wanted to stay away from that particular minefield. You know, whether or
not you need to be invoking lexical scope for it to be considered a closure,
etc.

Well, I could do all this roll-your-own stuff in my OO language too, but
frankly I'd rather have the compiler do it, and take my chances with good
class libraries. Frankly I cant think of too many occasssions when I've
needed to repeatedly combine just the one function of a class with one from
another. If you find yourself having to do that often its a sign of an
ill-designed class library that lacks coherence (Although the lack of
multiple inheritance in Java has hurt on occassion)

> This is deeper than one might think at first. For example, when
> implementing subclasses, you're often forced to implement tons of
> nitty-gritty little functions that aren't needed for the concrete
> application you have in mind, but you have to implement them anyway
> because the parent class requires them.
> In the FP world, I just write those functions that I actually need.

Again you need to use the right tools. Eclipse (and other IDEs) will
generate the class for you with all the inherited abstract methods stubbed
out. So if you don't want 'em, don't implement em (personally, I change the
default code generator to generate a "throw new NotImplementedException();"
just to be sure but that's just a matter of personal preference).

> > In addition, you can't take advantage of inheritance so you really
> > are forced to define all m*n functions. Yes, it does the job but it
> > hardly looks like a win to me.
>
> Typical FPLs don't even have inheritance, they use different mechanisms.
> They are most similar to C++'s templates (but better).
> I.e. you take an existing implementation, instantiate a few parameters,
> and you almost have what you want.
> It's more disciplined in a sense (because you can't wilfully override
> functions with something subtly different), yet flexible enough.

OK, I'll concede you the wilful overriding bit. That's a problem of a lack
of semantic typing in most OO languages.

> >>>> The advantage is: you don't have to inherit from a common
> >>>> "CanvasItem" superclass that may be polluting your namespace.
> >>>> [...]
> >>>
> >>> I am not sure what you mean by "polluting the namespace"
> >>
> >> If I inherit the CanvasItem class, my new subclass automatically
> >> contains all the stuff that was declared in the superclass, whether
> >> I want it or not.
> >
> > Well that goes back to the issue of whether your inheritance
> > hierarchy was appropriate to start with. Again think of the
> > WindowWithScrollBar class. If I add stuff to the Window base class,
> > then yes I would want WindowWithScrollBar to reflect that too. If
> > not, then add it privately.
>
> No, I didn't mean that.
> Say the Window class contains a GdiHandle member. It's private since
> it's doing very, very crufty internal stuff, so the subclass can't even
> access it.
> Yet when the subclass declares a GdiHandle member, it has a name clash.

And for a very good reason! if the base class introduced GdiHandler, there's
a goodly possibility that whatever code you had in your derived class may be
obsoleted. So it doesn't surprise me that it breaks your derived class.

> Particularly classes like Window tend to have far more than 100 members.
> Now that's a full namespace!
> (Been there, done that - I recently spent the three years working on a
> OO GUI library, which weighed in at a six-digit LoC count...)
>
> >> If the superclass is revised, it may acquire new machinery and
> >> hence new names. Any subclass that happens to use the same name
> >> must be rewritten.
> >
> > That's what refactoring tools are for...
>
> If refactoring tools were a solution, then namespace pollution wouldn't
> be a problem.
> Specifically, things get more difficult if you're the author of the
> subclass and the superclass is maintained (and changed) by somebody else
> - particularly if you get a new version of the library with all-new and
> all-changed internals.
> Things get even more difficult if you're the author of the superclass
> and forced to stick with the names you already used because most of the
> subclass authors don't have refactoring tools to begin with.

> (BTW I haven't heard of a *working* refactoring tools for C++ *g* - no
> surprise, the C++ semantics is very tricky, and any tool that does code
> modification at a large scale must "know" about the ins and outs of
> every detail.
> Of course, that's just C++, not OO in general.)

I stopped using C++ years ago. If enough people do that, it might just go
away. (Yeah right.)

cheers
-sri

> Regards,
> Jo


Andreas Rossberg

unread,
Jun 25, 2004, 11:22:09 PM6/25/04
to
"I spy" <s_ned...@yahoo.com> wrote:
>
> I see what you're doing but in fact your use of overloading is gratuitous.
> At the time you call doit, you (as in the client code) know what type of
> argument you're calling it on - that's the only way Haskell can possibly
> resolve it.

No, the type at which a method is applied is not always statically
derivable. Here is a simple (admittedly stupid) counter example:

f :: a -> Bool
f x n = if n > 0 then f [x] (n-1) else x == x

The method instance used for (==) depends on n. It will be the Eq
instance for some list type nested n times.

> That is, the example would have worked equally well if you had
> doitT1 and and a doitT2, calling whichever was appropriate.

Yes, if the type at which doit is applied is statically determinable
(which indeed is the case most of the times). That would be an
optimisation that trades space for time.

Likewise, it is perfectly viable for a C++ compiler to specialise doit
whenever it can statically determine the precise class of the argument
passed to it. It would not change the semantics of the program. (Well,
almost, because IIRC, the function address must be unique. That is,
the optimisation could only be applied if the address is not taken, or
if doit is only ever used with one and the same class.)

> In your C++ code as you have it, the argument to doit could
> be either a T1 or a T2 (for example you're iterating over a list of
> Examples, eacho of which could be a T1 or a T2), *and it is not possible for
> the compiler to determine which*.

Same in Haskell, when you have a list of existentials.

Cheers,

- Andreas

Andreas Rossberg

unread,
Jun 25, 2004, 11:47:58 PM6/25/04
to
ross...@ps.uni-sb.de wrote:
>
> f :: a -> Bool
> f x n = if n > 0 then f [x] (n-1) else x == x

Oops, should have been

f :: Eq a => a -> Int -> Bool

- Andreas

Dirk Thierbach

unread,
Jun 26, 2004, 9:13:07 AM6/26/04
to
I spy <s_ned...@yahoo.com> wrote:
> Um, perhaps not. In your C++ code as you have it, the argument to doit could
> be either a T1 or a T2 (for example you're iterating over a list of
> Examples, eacho of which could be a T1 or a T2), *and it is not possible for
> the compiler to determine which*.

Yes. Same in the Haskell code: The argument can either be T1 or T2
(or anything else that is an instance of Example), *and it is not possible
for the compiler to determine which*. Look at the type of doit: It doesn't
mention either T1 or T2. It only mentions Example, as in the C++ code.

I could even put doit into a module, compile this module, and then
later use it in another module where I declare a third datatype T3.
The compiler has no way to know that I will later write such a module
when it compiles the module with doit.

What's so difficult to understand here?

- Dirk

I spy

unread,
Jun 26, 2004, 11:56:41 AM6/26/04
to

"Andreas Rossberg" <ross...@ps.uni-sb.de> wrote in message
news:b20b8d03.04062...@posting.google.com...

> "I spy" <s_ned...@yahoo.com> wrote:
> >
> > I see what you're doing but in fact your use of overloading is
gratuitous.
> > At the time you call doit, you (as in the client code) know what type of
> > argument you're calling it on - that's the only way Haskell can possibly
> > resolve it.
>
> No, the type at which a method is applied is not always statically
> derivable. Here is a simple (admittedly stupid) counter example:
>
> f :: a -> Bool
> f x n = if n > 0 then f [x] (n-1) else x == x
Why can't the compiler rewrite this as

ff :: Eq a => a -> Int -> Bool -- where a is not a list type
ff x n = if n > 0 then flist [x] (n-1) else x == x

flist :: Eq a => [a] -> Int -> Bool
flist xs n = if n > 0 then flist [xs] (n-1) else xs == xs

Now you don't have any ambiguity at runtime.

BTW, I'm interested this not just for academic reasons. Run-time type
dispatch ala OO languages comes with both an execution and space cost. I was
always under the impresssion that functional languages did not have this
overhead. Hence my surprise on seeing gthe comparison to virtual methods in
the Tutorial

cheers

William Lovas

unread,
Jun 27, 2004, 6:19:14 AM6/27/04
to
In article <2k5klsF...@uni-berlin.de>, I spy wrote:
> Why can't the compiler rewrite this as
>
> ff :: Eq a => a -> Int -> Bool -- where a is not a list type
> ff x n = if n > 0 then flist [x] (n-1) else x == x
>
> flist :: Eq a => [a] -> Int -> Bool
> flist xs n = if n > 0 then flist [xs] (n-1) else xs == xs
>
> Now you don't have any ambiguity at runtime.

I think someone more well versed in the internals of one or more Haskell
compilers would have to answer this one, but...

> BTW, I'm interested this not just for academic reasons. Run-time type
> dispatch ala OO languages comes with both an execution and space cost. I was
> always under the impresssion that functional languages did not have this
> overhead. Hence my surprise on seeing gthe comparison to virtual methods in
> the Tutorial

...You might be interested in the paper, "Implementing Type Classes", by
John Peterson and Mark P. Jones, from June 1993's PLDI.

http://www.cse.ogi.edu/~mpj/pubs/pldi93.html

It explains how the runtime behavior of type classes is implemented with
dictionary passing. Perhaps you can compare this with the virtual method
lookup table implementation strategy typically used by OO languages.

I'm no expert, but as far as i can tell, Haskell type classes incur a
similar runtime cost to dynamic dispatch in OO languages.

cheers,
William

Andreas Rossberg

unread,
Jun 27, 2004, 6:26:41 AM6/27/04
to
"I spy" <s_ned...@yahoo.com> wrote:
>
> Why can't the compiler rewrite this as
>
> ff :: Eq a => a -> Int -> Bool -- where a is not a list type
> ff x n = if n > 0 then flist [x] (n-1) else x == x
>
> flist :: Eq a => [a] -> Int -> Bool
> flist xs n = if n > 0 then flist [xs] (n-1) else xs == xs
>
> Now you don't have any ambiguity at runtime.

Yes, you have (although I would not call the need for dynamic dispatch
an ambiguity). You haven't changed anything with flist, except for
making the function less polymorphic. Consider flist being applied as
follows:

flist [5] 3

It will recurse like

flist [[5]] 2
flist [[[5]]] 1
flist [[[[5]]]] 0
[[[[5]]]] == [[[[5]]]]

Hence you need equality on type [[[[Int]]]]. If you apply (flist [5]
4) you need equality on type [[[[[Int]]]]], and so forth. Obviously,
all of them require a different implementation.

Maybe it is becoming more obvious with the following variation:

f :: Eq a => a -> Int -> Int
f x n = if x == x && n == 0 then 42
else f (if even n then (x,x) else [x]) (n-1)

Now, (==) is applied in each recursion step. Depending on whether n is
even or odd, it is either a pair or a list of increasing nesting
depth, respectively.

> BTW, I'm interested this not just for academic reasons. Run-time type
> dispatch ala OO languages comes with both an execution and space cost. I was
> always under the impresssion that functional languages did not have this
> overhead. Hence my surprise on seeing gthe comparison to virtual methods in
> the Tutorial

Well, it's not an overhead of FP per se, but of the use of Haskell's
type class mechanism. And of course, that overhead can be avoided by
restricting the types of your functions, if the polymorphism is not
needed. Somewhat like using a non-virtual method in C++.

Cheers,

- Andreas

Malcolm Wallace

unread,
Jun 28, 2004, 9:15:22 AM6/28/04
to
ross...@ps.uni-sb.de (Andreas Rossberg) writes:

> f :: Eq a => a -> Int -> Int
> f x n = if x == x && n == 0 then 42
> else f (if even n then (x,x) else [x]) (n-1)

The inner 'if' conditional is type-incorrect (unless you have a
union type system for Haskell :-). However, you can straightforwardly
write the same code type-correctly like so:

f x n = if x == x && n == 0 then 42

else if even n then f (x,x) (n-1)
else f [x] (n-1)

and your argument about polymorphic recursion continues to hold.

Regards,
Malcolm

Andreas Rossberg

unread,
Jun 28, 2004, 9:33:47 AM6/28/04
to
Malcolm Wallace wrote:
>
>> f :: Eq a => a -> Int -> Int
>> f x n = if x == x && n == 0 then 42
>> else f (if even n then (x,x) else [x]) (n-1)
>
> The inner 'if' conditional is type-incorrect (unless you have a
> union type system for Haskell :-). However, you can straightforwardly
> write the same code type-correctly like so:

Oh yes, thanks! So much for last-minute editing.

Joachim Durchholz

unread,
Jun 29, 2004, 8:51:29 AM6/29/04
to
I spy wrote:

> "Joachim Durchholz" <j...@durchholz.org> wrote:
>
>> I spy wrote:
>>
>>> "Joachim Durchholz" <j...@durchholz.org> wrote:
>>>
>>> Perhaps I'm not following you. Let me see if I understand: You
>>> have several types T1...Tn which let says might inherit from one
>>> another in an OO language. In an OO language, there would also be
>>> m methods for each type (to keep things simple assume each type
>>> has the same named methods).
>>
>> Agreed until here.
>>
>>> Corresponding to this You define m*n curried functions.
>>
>> No, not at all. I'd define n curried functions - I'm not interested
>> in doing the other (m-1) functions to fill just a single list.
>
> OK, I was taking the general case, supposing the other functions were
> of interest - which is typical. Its not *often* you'll be using just
> one function out of a class.

Hmm... partly.
Most of the time, I'm interested just in a small subset of the functions
of a class. (Which makes me believe that the vast majority of classes is
bloated beyond sanity. Which, again, makes me believe that the
"everything should be in a class, and part of a datatype" claim often
heard in the OO camp is bogus: sometimes, a set of functions is just a
set of functions. It doesn't make sense to stick sin, cos, and ln into a
data type, they are just functions that operate on a data type, and if
OO languages had modules independently of classes, the classes would be
less bloated... but I digress.)

> But OK, let's just assume you're only interested in the one function.
> And I see below that you consider the multi function case.
>
>>> At run time you have a list of partially assigned functions
>>
>> Just for the record: These are called "curried functions". It's
>> also a simple case of closures.
>
> I wanted to stay away from that particular minefield. You know,
> whether or not you need to be invoking lexical scope for it to be
> considered a closure, etc.

I think that minefield is largely irrelevant. Lexical scope can always
be translated into an implicit list of parameters.
It's irrelevant to our discussion anyway :-)

Hmm... I never saw a class library that did the things the way I liked
them ;-)

And, let me repeat: it's *not* a roll-your-own version of OO.
First, what's a class in an OO language is usually spread all over the
data structures in an FPL, in the form of single-purpose functions.
There is no such thing as a strictly coupled data type, not in
conjunction with dispatching. (FPLs have abstract data types and tightly
coupled, encapsulated implementations for them. It's just that they
don't use dynamic dispatch for it.)

As I wrote below, it can be made into a roll-your-own version of OO
dispatch using records of closures. You still don't have local data in
these records, nor do you have inheritance, nor any of the other bells
and whistles (which is just as well: these records simulate just dynamic
dispatch, not the other features of OO, which are supplied via the ADT
mechanisms).

> Frankly I cant think of too many occasssions when I've needed to
> repeatedly combine just the one function of a class with one from
> another.

That's just because you're not used to doing it that way.

When doing OO design, you start with the objects and try to assign every
function to some object. You pass around the objects, so that the
functions that go with them are available with little ado.

When doing functional design, you start with what you want done. You use
the ADTs that are there, and occasionally you design a new ADT, but
mostly it's (variants of) lists and trees (there isn't much need felt
for collection abstractions).

> If you find yourself having to do that often its a sign of an
> ill-designed class library that lacks coherence

In OO, yes.

In an FPL, it's a standard tool in the toolbox.

The advantage of not having everything in its separate type is that
there are less barriers for using a type. If everything is a list, you
can apply the standard list functions to everything, without the need
for type acrobatics. In an OO language, I have to lay my type structure
out very carefully to avoid having barriers, and sometimes I'm forced to
choose the lesser of to evils.

>> This is deeper than one might think at first. For example, when
>> implementing subclasses, you're often forced to implement tons of
>> nitty-gritty little functions that aren't needed for the concrete
>> application you have in mind, but you have to implement them anyway
>> because the parent class requires them. In the FP world, I just
>> write those functions that I actually need.
>
> Again you need to use the right tools. Eclipse (and other IDEs) will
> generate the class for you with all the inherited abstract methods
> stubbed out.

The need for tool support is the hallmark of bad design :-)

Besides, these nitty-gritty functions will have to be implemented some
day. The ability to have the IDE generate the code for me just defers
the work, it doesn't eliminate it.

> So if you don't want 'em, don't implement em (personally, I change
> the default code generator to generate a "throw new
> NotImplementedException();" just to be sure but that's just a matter
> of personal preference).

It's not my experience that stubs remain unimplemented, if only for fear
that they might be, somewhere, somehow, called anyway even though I
*think* this won't happen. (This is very similar to static typing:
unless the compiler doesn't check it for me, I'm usually not 100% sure
that every single operation in my program is type correct.)

> OK, I'll concede you the wilful overriding bit. That's a problem of a
> lack of semantic typing in most OO languages.

Which isn't really feasible, even with Design by Contract in mind (I
have used it for several years, and while it's far, far better than
nothing, it doesn't and cannot cover all cases).

>>>>>> The advantage is: you don't have to inherit from a common
>>>>>> "CanvasItem" superclass that may be polluting your
>>>>>> namespace. [...]
>>>>>
>>>>> I am not sure what you mean by "polluting the namespace"
>>>>
>>>> If I inherit the CanvasItem class, my new subclass
>>>> automatically contains all the stuff that was declared in the
>>>> superclass, whether I want it or not.
>>>
>>> Well that goes back to the issue of whether your inheritance
>>> hierarchy was appropriate to start with. Again think of the
>>> WindowWithScrollBar class. If I add stuff to the Window base
>>> class, then yes I would want WindowWithScrollBar to reflect that
>>> too. If not, then add it privately.
>>
>> No, I didn't mean that. Say the Window class contains a GdiHandle
>> member. It's private since it's doing very, very crufty internal
>> stuff, so the subclass can't even access it. Yet when the subclass
>> declares a GdiHandle member, it has a name clash.
>
> And for a very good reason! if the base class introduced GdiHandler,
> there's a goodly possibility that whatever code you had in your
> derived class may be obsoleted. So it doesn't surprise me that it
> breaks your derived class.

Why on earth should the subclass care whether the superclass now
reimplements something that's perfectly working in the subclass?

Assuming the subclass uses the GdiHandle for something that's entirely
unrelated to what the superclass is doing (say, it's the handle to a
bitmap, while the superclass wants to refer to a cached window handle) -
then the class is entirely irrelevant.

The bad thing isn't that there may not be good reasons. The bad thing is
that the superclass and the subclass aren't properly encapsulated from
each other. They cannot be if the subclass uses internals of the superclass.

I have seen classes where the internals were delegated to separate
classes, just to avoid this kind of name clash. Which is just a way to
avoid implementation inheritance... and often that implementation class
would benefit from some template-style mechanism to make it more
adaptable to new situations.

Which is just the way things typically work in an FPL. You have an
implementation (a collection of functions that interoperate for some
purpose), collectively parameterized.
Then you have what would be a subclass. If you care to make it an ADT,
it links up with that service module, instantiates it with the correct
type and value parameters, and uses it.
The hassle involved with that it no more nor less than the hassle that
you have when inheriting, but it's *you* who select what functions are
in and what are out. And since the remaining infrastructure doesn't
expect a list of Windows, but just a list of "things that can execute
and return an int", you're free to leave out those parts of the
interface that don't make sense for your data type anymore.

And all this without losing safety :-)

Regards,
Jo

I spy

unread,
Jun 30, 2004, 6:43:52 AM6/30/04
to

"Joachim Durchholz" <j...@durchholz.org> wrote in message
news:cbrohh$368$1...@news.oberberg.net...
OO is really targetted at managing architectural dependencies in fairly
large code bases (its interesting that it didn't really take off until code
got to a certain size that architecture became an issue), not for
algorithmic code, and most gurus would probably name that (and parsing) as
not being the best applications for OO. Unf its a language restriction of
languages like Java that makes you stick everything in a class. I suppose
they were trying to encourage everyone to "do it the OO way". (Which reminds
me of an "OO program" that a boss of mine once wrote - it was one gigantic
class with about 50 odd methods in it. Basically a C program in C++
clothing).

As for bloated classes, the answer is to break them up into multuple
coherent abstract classes that you can combine mixin style.

> > But OK, let's just assume you're only interested in the one function.
> > And I see below that you consider the multi function case.
> >
> >>> At run time you have a list of partially assigned functions
> >>
> >> Just for the record: These are called "curried functions". It's
> >> also a simple case of closures.
> >
> > I wanted to stay away from that particular minefield. You know,
> > whether or not you need to be invoking lexical scope for it to be
> > considered a closure, etc.
>
> I think that minefield is largely irrelevant. Lexical scope can always
> be translated into an implicit list of parameters.
> It's irrelevant to our discussion anyway :-)

Whatever dude. You brought it up, not me!

Not a single one? What are you trying to do? :-)

> And, let me repeat: it's *not* a roll-your-own version of OO.
> First, what's a class in an OO language is usually spread all over the
> data structures in an FPL, in the form of single-purpose functions.
> There is no such thing as a strictly coupled data type, not in
> conjunction with dispatching. (FPLs have abstract data types and tightly
> coupled, encapsulated implementations for them. It's just that they
> don't use dynamic dispatch for it.)
>
> As I wrote below, it can be made into a roll-your-own version of OO
> dispatch using records of closures. You still don't have local data in
> these records, nor do you have inheritance, nor any of the other bells
> and whistles (which is just as well: these records simulate just dynamic
> dispatch, not the other features of OO, which are supplied via the ADT
> mechanisms).

Yes I got all that, but I'm still not sure exactly what your setup looks
like.

> > Frankly I cant think of too many occasssions when I've needed to
> > repeatedly combine just the one function of a class with one from
> > another.
>
> That's just because you're not used to doing it that way.
>
> When doing OO design, you start with the objects and try to assign every
> function to some object. You pass around the objects, so that the
> functions that go with them are available with little ado.
>
> When doing functional design, you start with what you want done. You use
> the ADTs that are there, and occasionally you design a new ADT, but
> mostly it's (variants of) lists and trees (there isn't much need felt
> for collection abstractions).
>
> > If you find yourself having to do that often its a sign of an
> > ill-designed class library that lacks coherence
>
> In OO, yes.
>
> In an FPL, it's a standard tool in the toolbox.
>
> The advantage of not having everything in its separate type is that
> there are less barriers for using a type. If everything is a list, you
> can apply the standard list functions to everything, without the need
> for type acrobatics. In an OO language, I have to lay my type structure
> out very carefully to avoid having barriers, and sometimes I'm forced to
> choose the lesser of to evils.

And this is where we get into the maintenance issue. Making everything a
list might do the job for now, but what if I really do need O(1) or
O(logn/nlogn) access down the road? OTOH, OO definitetly doesn't come for
free. There is a cost to having to anticipate what might change.

> >> This is deeper than one might think at first. For example, when
> >> implementing subclasses, you're often forced to implement tons of
> >> nitty-gritty little functions that aren't needed for the concrete
> >> application you have in mind, but you have to implement them anyway
> >> because the parent class requires them. In the FP world, I just
> >> write those functions that I actually need.
> >
> > Again you need to use the right tools. Eclipse (and other IDEs) will
> > generate the class for you with all the inherited abstract methods
> > stubbed out.
>
> The need for tool support is the hallmark of bad design :-)

Huh? You don't use macros in <insert favorite editor>? Or parenthesis
matching? Or syntax color coding? Is the usefulness (need?) for these things
a hallmark of a badly designed language?

> Besides, these nitty-gritty functions will have to be implemented some
> day. The ability to have the IDE generate the code for me just defers
> the work, it doesn't eliminate it.

We're going in circles here. If you need to implement them anyway, then
where's the extra labour you're complaining about?

> > So if you don't want 'em, don't implement em (personally, I change
> > the default code generator to generate a "throw new
> > NotImplementedException();" just to be sure but that's just a matter
> > of personal preference).
>
> It's not my experience that stubs remain unimplemented, if only for fear
> that they might be, somewhere, somehow, called anyway even though I
> *think* this won't happen. (This is very similar to static typing:
> unless the compiler doesn't check it for me, I'm usually not 100% sure
> that every single operation in my program is type correct.)
>
> > OK, I'll concede you the wilful overriding bit. That's a problem of a
> > lack of semantic typing in most OO languages.
>
> Which isn't really feasible, even with Design by Contract in mind (I
> have used it for several years, and while it's far, far better than
> nothing, it doesn't and cannot cover all cases).

Well there's always going to be exceptions in any real world problem (the
Birds can fly/Penguins example comes to mind). You have to deal with them as
best you can, and that might sometimes call for willful overriding.

> >>>>>> The advantage is: you don't have to inherit from a common
> >>>>>> "CanvasItem" superclass that may be polluting your
> >>>>>> namespace. [...]
> >>>>>
> >>>>> I am not sure what you mean by "polluting the namespace"
> >>>>
> >>>> If I inherit the CanvasItem class, my new subclass
> >>>> automatically contains all the stuff that was declared in the
> >>>> superclass, whether I want it or not.
> >>>
> >>> Well that goes back to the issue of whether your inheritance
> >>> hierarchy was appropriate to start with. Again think of the
> >>> WindowWithScrollBar class. If I add stuff to the Window base
> >>> class, then yes I would want WindowWithScrollBar to reflect that
> >>> too. If not, then add it privately.
> >>
> >> No, I didn't mean that. Say the Window class contains a GdiHandle
> >> member. It's private since it's doing very, very crufty internal
> >> stuff, so the subclass can't even access it. Yet when the subclass
> >> declares a GdiHandle member, it has a name clash.
> >
> > And for a very good reason! if the base class introduced GdiHandler,
> > there's a goodly possibility that whatever code you had in your
> > derived class may be obsoleted. So it doesn't surprise me that it
> > breaks your derived class.
>
> Why on earth should the subclass care whether the superclass now
> reimplements something that's perfectly working in the subclass?

But without a semantics and theorem prover and a lot of time on your hands
you aren't going to know whether or not it was an addition to or an
obsoleting. If the base class was introducing a concept that didn't exist
before and the concept had a name clash with one I already use, I think I'd
want to at least investigate and eliminate the potential for confusion for
future readers of my program. Remember also we're talking implementation
inheritance here, which as Bertrand Meyer points out is useful - but risky.

> Assuming the subclass uses the GdiHandle for something that's entirely
> unrelated to what the superclass is doing (say, it's the handle to a
> bitmap, while the superclass wants to refer to a cached window handle) -
> then the class is entirely irrelevant.
>
> The bad thing isn't that there may not be good reasons. The bad thing is
> that the superclass and the subclass aren't properly encapsulated from
> each other. They cannot be if the subclass uses internals of the
superclass.

If you're really bothered by it then use the public access methods

> I have seen classes where the internals were delegated to separate
> classes, just to avoid this kind of name clash. Which is just a way to
> avoid implementation inheritance... and often that implementation class
> would benefit from some template-style mechanism to make it more
> adaptable to new situations.
>
> Which is just the way things typically work in an FPL. You have an
> implementation (a collection of functions that interoperate for some
> purpose), collectively parameterized.
> Then you have what would be a subclass. If you care to make it an ADT,
> it links up with that service module, instantiates it with the correct
> type and value parameters, and uses it.
> The hassle involved with that it no more nor less than the hassle that
> you have when inheriting, but it's *you* who select what functions are
> in and what are out. And since the remaining infrastructure doesn't
> expect a list of Windows, but just a list of "things that can execute
> and return an int", you're free to leave out those parts of the
> interface that don't make sense for your data type anymore.

Well if you have anything that's supposed to look like an inheritance
hierarchy in your problem domain you've severely broken it and LSP doing
that. So I would say "don't do that!" I am not denying that the orthogonal
decomposition you have outlined isn't useful. But which way I break it up
should be a function of what my expectations are for the software I am
designing. I don't like having it forced on me by language shortcomings

> And all this without losing safety :-)

see my answer above

cheers
-sri
> Regards,
> Jo


Cristiano Sadun

unread,
Jun 30, 2004, 7:15:40 AM6/30/04
to
Joachim Durchholz <j...@durchholz.org> wrote in
news:cbrohh$368$1...@news.oberberg.net:

> Hmm... partly.
> Most of the time, I'm interested just in a small subset of the
> functions of a class. (Which makes me believe that the vast majority
> of classes is bloated beyond sanity. Which, again, makes me believe
> that the "everything should be in a class, and part of a datatype"
> claim often heard in the OO camp is bogus: sometimes, a set of
> functions is just a set of functions. It doesn't make sense to stick
> sin, cos, and ln into a data type, they are just functions that
> operate on a data type, and if OO languages had modules independently
> of classes, the classes would be less bloated... but I digress.)
>

Interestingly, OO can be seen as a way of carrying around a context in a
way that is cheap and usable automatically (by the compiler or runtime).

Note that the difference with, say, a procedural approach is only in the
nature of the context: for OO, it is the current class (or the system
for static-like methods); for procedures, it is simply the system.

"Everything should be in a class" is a way to say that, at applicative
level at least, everything has a context. An OO approach tends to
qualify that context explicitly, allowing the programmer to narrow it to
avoid errors and the compiler/runtime to detect more of the errors that
remain.

Even a set of library functions as sin, cos and ln does not exist in a
vacuum - their context is the language runtime, which in turn is an
abstraction of the platform. For example sin() on a certain platform may
give results different than on another (as opposed to its mathematical
counterparts), depending on the kind of algorithm with which is
computed.

So their perfect placing is in a class which represents the mathematical
capacities of the plaftorm, and of which as many instances exist as many
different mathematical toolkits we have - typically one. If this "one"
is an assumption of the language (as it often is), you will have a class
"Mathematics" with static-like methods or a library of similarly static
functions. But they still will be equivalent to methods of an (sometimes
implicit) "runtime" object.

Class bloating, on the contrary, comes from bad partitioning and classes
assuming too many roles - a situation where the context become much less
relevant than the specific method which is running, and we fall back to
a procedural approach.

The only "benign" form of bloating is that given by overloads - which
typically are only a way to make life easier for a class' client code
and count as a single method.

Andreas Rossberg

unread,
Jun 30, 2004, 9:03:12 AM6/30/04
to
I spy wrote:
>>
>>The need for tool support is the hallmark of bad design :-)
>
> Huh? You don't use macros in <insert favorite editor>?

No.

> Or parenthesis matching? Or syntax color coding?

Occasionally.

> Is the usefulness (need?) for these things
> a hallmark of a badly designed language?

Actually, I'd say yes indeed: it is evidence for a language inducing too
much syntactic noise and boilerplate, and lacking proper abstraction
facilities. ;-)

- Andreas

Mark S. Hathaway

unread,
Jun 30, 2004, 12:47:36 PM6/30/04
to
Cristiano Sadun wrote:
> Joachim Durchholz <j...@durchholz.org> wrote in
> news:cbrohh$368$1...@news.oberberg.net:
>
>>Most of the time, I'm interested just in a small subset of the
>>functions of a class. (Which makes me believe that the vast majority
>>of classes is bloated beyond sanity. Which, again, makes me believe
>>that the "everything should be in a class, and part of a datatype"
>>claim often heard in the OO camp is bogus: sometimes, a set of
>>functions is just a set of functions. It doesn't make sense to stick
>>sin, cos, and ln into a data type, they are just functions that
>>operate on a data type, and if OO languages had modules independently
>>of classes, the classes would be less bloated... but I digress.)
>
> Interestingly, OO can be seen as a way of carrying around a context in a
> way that is cheap and usable automatically (by the compiler or runtime).
>
> Note that the difference with, say, a procedural approach is only in the
> nature of the context: for OO, it is the current class (or the system
> for static-like methods); for procedures, it is simply the system.

And here I thought OO was "the way programmers think" and was created
to enable programmers to design and write programs better. But, you're
saying it's just a better way to manage the execution code. Amazing.

> "Everything should be in a class" is a way to say that, at applicative
> level at least, everything has a context. An OO approach tends to
> qualify that context explicitly, allowing the programmer to narrow it to
> avoid errors and the compiler/runtime to detect more of the errors that
> remain.

Type checking a la OO? Yes, I've thought of that and have read
discussions about it. But, I don't know that this was ever given
as a primary reason for OO to exist.

If one considers a dynamic language like Smalltalk, where
there's no specific type-checking done, that reason for
having classes is only a small bit of the story - perhaps
an afterthought.

...

> Class bloating, on the contrary, comes from bad partitioning and classes
> assuming too many roles - a situation where the context become much less
> relevant than the specific method which is running, and we fall back to
> a procedural approach.
>
> The only "benign" form of bloating is that given by overloads - which
> typically are only a way to make life easier for a class' client code
> and count as a single method.

I've seen procedural programs where a function has a parameter
list a mile long. I think sometimes OO was created to do away
with those. By "carrying" the context and function together there's
no need for all those long parameter lists. But, there is a slight
lessening of flexibility caused by the wall around the function.

Robert C. Martin

unread,
Jun 30, 2004, 5:19:29 PM6/30/04
to
On Wed, 30 Jun 2004 11:43:52 +0100, "I spy" <s_ned...@yahoo.com>
wrote:


>OO is really targetted at managing architectural dependencies in fairly
>large code bases (its interesting that it didn't really take off until code
>got to a certain size that architecture became an issue),

"targeted" is probably not the word I would use. I don't think the
creators of OO were targeting anything. I think, for them, OO was a
happy accident.

OO is *useful* for managing dependencies in code bases that are large,
it's true. But it's also of use in moderate to small code bases as
well.

OO took off as soon as there were languages that the industrial
programmers had confidence in. That they didn't have confidence in
Smalltalk in the 80's is unfortunate, but not surprising. That they
*did* have confidence in C++ is also not surprising, given it's
lineage.

>not for
>algorithmic code, and most gurus would probably name that (and parsing) as
>not being the best applications for OO.

OO is applicable for any application that can benefit from decoupling
and dependency management. Individual algorithms are not always the
best candidates, but should not be excluded. For example, sort
algorithms are often implemented polymorphically using OO structures.

>Unf its a language restriction of
>languages like Java that makes you stick everything in a class.

Yes, and it would be convenient if Java relaxed that restriction. On
the other hand, the restriction is not that big of a deal. The global
scope is really just an un-named class.

>I suppose
>they were trying to encourage everyone to "do it the OO way".

Maybe, but I don't think they were that naive. Instead I think they
were trying to make sure that every binary module had a name.
Remember that all classes in Java are compiled down into .class files.

>(Which reminds
>me of an "OO program" that a boss of mine once wrote - it was one gigantic
>class with about 50 odd methods in it. Basically a C program in C++
>clothing).

Yes. OO is a superset of the procedural paradigm. You can write
procedural programs in any OO language, but you can't write OO
programs in any procedural language.

-----
Robert C. Martin (Uncle Bob)
Object Mentor Inc.
unclebob @ objectmentor . com
800-338-6716

"The aim of science is not to open the door to infinite wisdom,
but to set a limit to infinite error."
-- Bertolt Brecht, Life of Galileo

Joachim Durchholz

unread,
Jun 30, 2004, 7:41:47 PM6/30/04
to
I spy wrote:

> "Joachim Durchholz" <j...@durchholz.org> wrote:
>>
>> Hmm... I never saw a class library that did the things the way I
>> liked them ;-)
>
> Not a single one? What are you trying to do? :-)

Oh, simple things. Like a GUI library that sat on top of GDI and created
all things of nifty abstractions (most notably validation, a rule-based
framework for automatically resizing subcontrols when the enclosing
control changed size, a homegrown table control that could host any
other controls, and a tab order mechanism that was independent of
control creation order - none of these were mean feats *ggg*) (in
fairness, I must add that we were a team of three *ggggg*)

>> And, let me repeat: it's *not* a roll-your-own version of OO.
>> First, what's a class in an OO language is usually spread all over
>> the data structures in an FPL, in the form of single-purpose
>> functions. There is no such thing as a strictly coupled data type,
>> not in conjunction with dispatching. (FPLs have abstract data types
>> and tightly coupled, encapsulated implementations for them. It's
>> just that they don't use dynamic dispatch for it.)
>>
>> As I wrote below, it can be made into a roll-your-own version of OO
>> dispatch using records of closures. You still don't have local
>> data in these records, nor do you have inheritance, nor any of the
>> other bells and whistles (which is just as well: these records
>> simulate just dynamic dispatch, not the other features of OO, which
>> are supplied via the ADT mechanisms).
>
> Yes I got all that, but I'm still not sure exactly what your setup
> looks like.

Um... time for an example.

Say the task is to have a list of things that can display on a screen.

In the OO world, I need to have a type Displayable, with a
draw(where:Screen) method. If I need to display something that doesn't
inherit from Displayable (maybe because it's from the class library of a
third party), I have to write some wrapper code (if Displayable is a
large class with many, in this context unneeded features, what I
actually want to do is buried in tons of other code, either lots of
stubs or lots of wrapper code).

In the FPL world, I make a list of curried functions.
I wrap every object that I want to draw in a function that will draw it
on a Screen object.
So, if I have a Rectangle type that offers me
draw_rect x,y,w,h:int; where:Screen
I say
new_list = cons
(draw_rect 1 15 50 60 _)
-- invented syntax for creating a curried function
old_list
to prepend a 50x60 rectangle at (1,15) to old_list.
If I need a circle, I do likewise.
If I need a bitmap, I do something like
(draw_bitmap (bitmap_from_file "foo.bmp") 50 80 _)

What I get is a list of functions that will draw a given scene on the
screen. Or on something else (if the various drawing routines accept
something more general than a Screen).

For traditional thinking, this list is just a series of functions
waiting to execute.
In a functional context, this isn't less true, but the list is also just
data. It *is* the scene.

If I want to do hit-testing (i.e. associate a given point with a
geometric figure), I create a similar list. I'm free to leave out those
scene elements that are irrelevant for hit-testing (and don't have to go
back to the Displayable class and add a boolean attribute that says
whether it can be found during hit testing - besides, which elements
hit-test and which don't may vary due to circumstances, so this isn't a
really satisfactory solution anyway). I can add elements that aren't
Displayable but require hit-testing anyway (e.g. invisible areas like
"anywhere on the table line, between the controls on it").

In short, a class hierarchy forces me to make many design decisions,
quite far up in the hierarchy.
In an FPL, I can defer many of these decisions. I can defer them until I
really need to make them.

>> The advantage of not having everything in its separate type is that
>> there are less barriers for using a type. If everything is a list,
>> you can apply the standard list functions to everything, without
>> the need for type acrobatics. In an OO language, I have to lay my
>> type structure out very carefully to avoid having barriers, and
>> sometimes I'm forced to choose the lesser of to evils.
>
> And this is where we get into the maintenance issue. Making
> everything a list might do the job for now, but what if I really do
> need O(1) or O(logn/nlogn) access down the road?

That's a valid criticism. It's difficult to replace code that uses lists
with something that uses other, more advanced data structures.

On the other hand, the issue is being addressed. There are type classes
and functors (which are different ways of abstracting out commonalities
like iteration-over-a-bag and similar stuff, i.e. can be used as ADTs).

> OTOH, OO definitetly doesn't come for free. There is a cost to having
> to anticipate what might change.

Definitely :-)

>> Besides, these nitty-gritty functions will have to be implemented
>> some day. The ability to have the IDE generate the code for me just
>> defers the work, it doesn't eliminate it.
>
> We're going in circles here. If you need to implement them anyway,
> then where's the extra labour you're complaining about?

Because if I'm forced to implement them right now, at a point in the
design where I don't need them, I'll pretty sure make mistakes. I'll
want to get over with that just to get my code working, so I'll sloppily
hack something together and test it as quickly as possible (i.e. usually
not at all - I have a deadline to meet, and my superior won't understand
that I missed by a week just because I had to clean up some service
class and write code that isn't even used).
Half a year after that, this sloppy, scantily-tested code will come back
and bite me. Colleagues might rely on those nominally-working functions,
set their deadlines according to their expectations, just to find that
the code they're relying on doesn't really work.

I've been on both sides of this fence far too often to find much comfort
in the idea of "abstract everything in classes, and if a new subclass is
called for, you must *immediately* implement *everything* in it".

I could do stubs. That would have the advantage that the
untested/not-yet-done parts of the class are clearly marked.
However, this moves a large part of static checking back into the
dynamic domain - these stubs won't be detected by the compiler, they
will fail at run-time.

The functional approach is more pragmatic here. Write those functions
that you need, when you need them. Ironically, I feel FPLs are far
nearer to Extreme Programming practices in this respect than OO
languages :-)

>>> OK, I'll concede you the wilful overriding bit. That's a problem
>>> of a lack of semantic typing in most OO languages.
>>
>> Which isn't really feasible, even with Design by Contract in mind
>> (I have used it for several years, and while it's far, far better
>> than nothing, it doesn't and cannot cover all cases).
>
> Well there's always going to be exceptions in any real world problem
> (the Birds can fly/Penguins example comes to mind). You have to deal
> with them as best you can, and that might sometimes call for willful
> overriding.

Which is again a case for not doing it with type hierarchies :-)

(Oh, the contortions I had to make to accommodate such cases in an
otherwise perfectly class hierarchy... boolean members like "can_fly"
which had to be properly initialized and kept correct at all times,
assumptions that these members could never change during the lifetime of
an object that turned out to be wrong later, and - worst of all - having
to add such flags very, very high up the class hierarchy, possibly
breaking any code that introduced its own can_fly attribute, for
potentially different purposes... you're recalling some very ugly
memories in me - not that that should be considered your fault *g*.)

Thanks for making my point: that subclass inheritance is unmodular :-)

>> Assuming the subclass uses the GdiHandle for something that's
>> entirely unrelated to what the superclass is doing (say, it's the
>> handle to a bitmap, while the superclass wants to refer to a cached
>> window handle) - then the class is entirely irrelevant.
>>
>> The bad thing isn't that there may not be good reasons. The bad
>> thing is that the superclass and the subclass aren't properly
>> encapsulated from each other. They cannot be if the subclass uses
>> internals of the superclass.
> If you're really bothered by it then use the public access methods

Which usually aren't available - that GdiHandle thing was supposed to be
strictly internal.
Besides, we've been talking about name clashes in the subclass. These
happen independently of whether the member is externally visible or not.

> Well if you have anything that's supposed to look like an inheritance
> hierarchy in your problem domain you've severely broken it and LSP
> doing that. So I would say "don't do that!"

Exactly.
Interface inheritance (i.e. subtyping) can be a useful tool to
streamline interfaces.
Implementation inheritance is - according to my experience - not worth
the risks. It should be replaced by good abstraction and reuse
facilities that use other means (e.g. modules that can be parameterized
with types and values, where the values might be functions or closures).

Of course, that's just my personal view :-)

> I am not denying that the orthogonal decomposition you have outlined
> isn't useful. But which way I break it up should be a function of
> what my expectations are for the software I am designing. I don't
> like having it forced on me by language shortcomings

If implementation inheritance is the only or the main way of reusing
code, than *that* is a language shortcoming.
The alternatives that I named in the above paragraph are just as
convenient (if done properly, syntactically and semantically), but far
more safe.

IMNSHO ;-)

Regards,
Jo

Thomas Gagne

unread,
Jun 30, 2004, 11:25:49 PM6/30/04
to

Robert C. Martin wrote:
> On Wed, 30 Jun 2004 11:43:52 +0100, "I spy" <s_ned...@yahoo.com>
> wrote:
>
>
>
>>OO is really targetted at managing architectural dependencies in fairly
>>large code bases (its interesting that it didn't really take off until code
>>got to a certain size that architecture became an issue),
>
>
> "targeted" is probably not the word I would use. I don't think the
> creators of OO were targeting anything. I think, for them, OO was a
> happy accident.

Robert, you know better than that! Alan Kay wanted to do the most profound
thing he could as best as could be done. It wasn't an accident. It was
deliberate.


>
> OO is *useful* for managing dependencies in code bases that are large,
> it's true. But it's also of use in moderate to small code bases as
> well.
>
> OO took off as soon as there were languages that the industrial
> programmers had confidence in. That they didn't have confidence in
> Smalltalk in the 80's is unfortunate, but not surprising. That they
> *did* have confidence in C++ is also not surprising, given it's
> lineage.
>

An odd perspective on history. OO requires a different perspective on code.
Given its uphill battle (and the same shortsightedness that brought us the
Y2K) bug it's little wonder C++ was as popular as it was, riding the coat
tails of both C and OO. I don't know which provided the greater momentum but
that has been long debated here already and exhaustively.

Of course, it has been slow these early days of summer...
>

Joachim Durchholz

unread,
Jul 1, 2004, 5:58:43 AM7/1/04
to
Thomas Gagne wrote:

>
> Robert C. Martin wrote:
>
>> "targeted" is probably not the word I would use. I don't think the
>> creators of OO were targeting anything. I think, for them, OO was a
>> happy accident.
>
> Robert, you know better than that! Alan Kay wanted to do the most
> profound thing he could as best as could be done. It wasn't an
> accident. It was deliberate.

I think Robert was referring to the creators of Simula, Ole-Johan Dahl
and Kristen Nygaard.
(Simula predates Smalltalk by approximagely a decade, and is generally
considered to be the first OO language.)

Regards,
Jo

Cristiano Sadun

unread,
Jul 1, 2004, 9:45:48 AM7/1/04
to
"Mark S. Hathaway" <hath...@marshall.edu> wrote in news:40e2b655
@alpha.wvnet.edu:

> And here I thought OO was "the way programmers think" and was created
> to enable programmers to design and write programs better. But, you're
> saying it's just a better way to manage the execution code. Amazing.

Well, there was an implicit "from that point of view" ;)

About the way programmers think, I seem to find as many different ways as
programmers, so I wouldn't know. Certainly, was created to enable
programmers etc. A better way to manage execution code is one of the
aspects of that, dont you agree?

> Type checking a la OO? Yes, I've thought of that and have read
> discussions about it. But, I don't know that this was ever given
> as a primary reason for OO to exist.

Wasn't thinking not much of type checking as of scope checking.
In a procedure you have the local scope (the procedure stack) and the
external global scope, which contains all the state which can't (or
won't) be carried by the parameter list+local variables. The global
scope, for any nontrivial application, tends to grow quickly and be at
any rate bigger than the local. If you want to partition the global scope
to "make order", you have to do it by hand.

On the other side, with classes, you have the local scope (the method
stack), the class scope (the class attributes) and an external global
scope (at the very least, everything which is accessible statically); and
it takes a little more effort to go the global scope than to stay within
the smaller class scope.. not less effort. In other words, in a class
method, "this" is implicit; in a procedure "global" is implicit.

In general, "smaller" means easier to understand, track and manage etc.
Hence the "better" (or at least its "enabling": I *did* see early
programs written in an OO lanaguage but made by one huge class with
dozens of member variables.. but not lately, to say the truth :).



> If one considers a dynamic language like Smalltalk, where
> there's no specific type-checking done, that reason for
> having classes is only a small bit of the story - perhaps
> an afterthought.

No doubt. I find it nevertheless interesting because it's somewhat less
obvious than other reasons. I remember "viewing" it for the first time
when I was into lambda-calculus, continuations and denotational semantics
in general - where the context is literally (and mathematically) carried
around in a very compact form.

> I've seen procedural programs where a function has a parameter
> list a mile long. I think sometimes OO was created to do away
> with those.

Yes, you just have one more place to put all that "context" which doesn't
make sense globally, but is still shared by a good number of related
methods.

> By "carrying" the context and function together there's
> no need for all those long parameter lists. But, there is a slight
> lessening of flexibility caused by the wall around the function.

Yep. At the very least, the programmer must make an explicit effort to go
past that wall to reach the external scope (and with some languages, he
can't). Still, my experience's that it's price worth paying.

Robert C. Martin

unread,
Jul 1, 2004, 10:14:35 AM7/1/04
to
On Wed, 30 Jun 2004 23:25:49 -0400, Thomas Gagne
<tga...@wide-open-west.com> wrote:

>
>
>Robert C. Martin wrote:
>> On Wed, 30 Jun 2004 11:43:52 +0100, "I spy" <s_ned...@yahoo.com>
>> wrote:
>>
>>
>>
>>>OO is really targetted at managing architectural dependencies in fairly
>>>large code bases (its interesting that it didn't really take off until code
>>>got to a certain size that architecture became an issue),
>>
>>
>> "targeted" is probably not the word I would use. I don't think the
>> creators of OO were targeting anything. I think, for them, OO was a
>> happy accident.
>
>Robert, you know better than that! Alan Kay wanted to do the most profound
>thing he could as best as could be done. It wasn't an accident. It was
>deliberate.

Kay was not the originator of OO. That honor belongs to Kristen
Nygaard and Ole-Johan Dahl. They were fiddling around with Algol in
the mid '60s and came up with a language named Simula. This language
influenced both Kay and Stroustrup.

I'm no expert on Kay, but as I recall it, Kay was interested in
creating tools, not languages so much. He wanted the Dynabook. For
him, Smalltalk was a means to that end. Later (if I remember
correctly) he said that he wished he'd never created Smalltalk. I'll
grant you that Kay was being deliberate. I doubt he thought that the
outcome of his work would help lead the industry towards C++, Java,
and C#.

Cristiano Sadun

unread,
Jul 1, 2004, 10:33:37 AM7/1/04
to
Thomas Gagne <tga...@wide-open-west.com> wrote in
news:feudnZUgrKm...@wideopenwest.com:

> An odd perspective on history. OO requires a different perspective on
> code. Given its uphill battle (and the same shortsightedness that
> brought us the Y2K) bug it's little wonder C++ was as popular as it
> was, riding the coat tails of both C and OO. I don't know which
> provided the greater momentum but that has been long debated here
> already and exhaustively

Hm. It seems to me that, outside the academia or newsgroups, the real
rationale under selecting this or that approach (or language, etc) is often
the line of least resistance; or, in other terms, the ratio between
perceived possible benefits and perceived effort.

Take programmers: if a generalization can be done, they're often interested
in new approaches - especially if they promise to make life easier; but the
short term effort mustn't be too big - even potential huge rewards tend not
to be enough if they are.

At the times, many people knew C. C++ had similar syntax, used familiar
mechanisms for source modularization, promised not to require much effort
to take care of aspects C programmers care about (namely, performance),
wasn't overly restrictive etc.

I chose it for all these reasons (and, truth be told, since I had
reverently read a copy of "OOP in C++", and I barely knew of the
alternatives or they were too expensive for a CS student). No matter that
these very reason, in the log run, are exactly the weaknesses of C++. It
was just, at the start, least resistance.

I suspect lots of people did the same.

Thomas Gagne

unread,
Jul 1, 2004, 11:27:00 AM7/1/04
to
Cristiano Sadun wrote:
> "Mark S. Hathaway" <hath...@marshall.edu> wrote in news:40e2b655
> @alpha.wvnet.edu:
>
>
>>And here I thought OO was "the way programmers think" and was created
>>to enable programmers to design and write programs better. But, you're
>>saying it's just a better way to manage the execution code. Amazing.
>
>
> Well, there was an implicit "from that point of view" ;)
>
> About the way programmers think, I seem to find as many different ways as
> programmers, so I wouldn't know. Certainly, was created to enable
> programmers etc. A better way to manage execution code is one of the
> aspects of that, dont you agree?

I wouldn't trivialize it to the way programmers think, but in broader terms it
seems to more accurately reflect the world around us, in the sense it is
filled with things that are like other things and that each has its own
behaviors and state.

A better way to manage code seems to be an artifact of the languages (some
better than others) and their tools.
>
>

Thomas Gagne

unread,
Jul 1, 2004, 12:09:22 PM7/1/04
to

Robert C. Martin wrote:
<snip>

>
> Kay was not the originator of OO. That honor belongs to Kristen
> Nygaard and Ole-Johan Dahl. They were fiddling around with Algol in
> the mid '60s and came up with a language named Simula. This language
> influenced both Kay and Stroustrup.

Nygaard and Dahl have recently been given (IMO) more credit for OO than they
deserve (heresy, I know). Kay's inspiration came from multiple places. Kay's
first inspiration came from the Burroughs 220, a file format that included
three parts, the data, the procedures for accessing the data, and pointers to
the procedures. The B220's ideas were taken further in the B5000, including
bytecodes.

Going from Simula's 64 keywords to Smalltalk's six is hardly evidence of
Simula's representing anything as profound as what Smalltalk did to OO
programming.

A light came on when he read the listing of an Algol compiler hacked into
something called Simula (I notice we don't give credit to the Algol people for
inventing simulation languages). Nor do the revisionists give enough credit
to Wirth's EULER which was also influential.

So, they may have been shoulders he stood on to see further, but they were not
the only shoulders and Kay was the fist to recognize what he saw. I agree
some credit is deserved, but not the honor of inventing OO.

As to the direction things have gone, programmers have proven to have an
affinity for keywords and static types - neither of which would have been
Smalltalk influences, and I doubt Nygaard and Dahl would want credit for that.
I think Stroustrup, Gosling, and the C# folks deserve the honor for giving
programming shops what they want - more keywords, because keywords must
represent sophistication.

Even the ACM recognized Smalltalk as being the first complete OOP when it
presented Kay the 2003 Turing award.

>
> I'm no expert on Kay, but as I recall it, Kay was interested in
> creating tools, not languages so much. He wanted the Dynabook. For
> him, Smalltalk was a means to that end. Later (if I remember
> correctly) he said that he wished he'd never created Smalltalk. I'll
> grant you that Kay was being deliberate. I doubt he thought that the
> outcome of his work would help lead the industry towards C++, Java,
> and C#.

I don't recall him saying that. What I think you may be referring to was:

"Just a gentle reminder that I took some pains at the last OOPSLA to try to
remind everyone that Smalltalk is not only NOT its syntax or the class
library, it is not even about classes. I'm sorry that I long ago coined the
term "objects" for this topic because it gets many people to focus on the
lesser idea.

"The big idea is "messaging" -- that is what the kernal of Smalltalk/Squeak is
all about (and it's something that was never quite completed in our Xerox PARC
phase). The Japanese have a small word -- mao for "that which is in between"
-- perhaps the nearest English equivalent is "interstitial". The key in making
great and growable systems is much more to design how its modules communicate
rather than what their internal properties and behaviors should be."

Odd, that what he thinks is the "lesser" idea is what everyone seems to have
promoted in subsequent languages (C++, Java, C#), and that gets the most
passioned debate.

<http://pbl.cc.gatech.edu:8080/cs2390/1447>

Mark S. Hathaway

unread,
Jul 2, 2004, 12:28:51 AM7/2/04
to
Cristiano Sadun wrote:
> "Mark S. Hathaway" <hath...@marshall.edu> wrote in news:40e2b655
> @alpha.wvnet.edu:
>
>>And here I thought OO was "the way programmers think" and was created
>>to enable programmers to design and write programs better. But, you're
>>saying it's just a better way to manage the execution code. Amazing.
>
> Well, there was an implicit "from that point of view" ;)
>
> About the way programmers think, I seem to find as many different ways as
> programmers, so I wouldn't know. Certainly, was created to enable
> programmers etc. A better way to manage execution code is one of the
> aspects of that, dont you agree?

The compiled version might somehow manage execution code better,
but there's no reason the OO source code we're getting used to
would be the only way to get there. Note, I'm not suggesting an
alternative at this point, just ruminating.

>>Type checking a la OO? Yes, I've thought of that and have read
>>discussions about it. But, I don't know that this was ever given
>>as a primary reason for OO to exist.
>
> Wasn't thinking not much of type checking as of scope checking.
> In a procedure you have the local scope (the procedure stack) and the
> external global scope, which contains all the state which can't (or
> won't) be carried by the parameter list+local variables. The global
> scope, for any nontrivial application, tends to grow quickly and be at
> any rate bigger than the local. If you want to partition the global scope
> to "make order", you have to do it by hand.

Yes, managing large globs of data and related functions
does seem to demand some enforcable solution.

Having one global data context with a zillion variables
and constants with longish names is nobody's idea of fun.
Having a zillion modules with a few bits of data for each
is, we're discovering, not so easy either.

Divide-and-conquer is a terrific method of dealing with
large tasks, so I think modules are likely to remain.
Some other parts of OO seem important too: encapsulation
and abstraction.

Come to think of it, what parts of current OO languages
are clearly wrong or a problem?

Is our next language just like the current ones, but with
even more power. Or, is it similar to current ones, but
with some reigning in of side effects we hadn't expected
when they (these OOPLs) were first created?

> On the other side, with classes, you have the local scope (the method
> stack), the class scope (the class attributes) and an external global
> scope (at the very least, everything which is accessible statically); and
> it takes a little more effort to go the global scope than to stay within
> the smaller class scope.. not less effort. In other words, in a class
> method, "this" is implicit; in a procedure "global" is implicit.

Improved naming and code writing...trivial really, but useful.

> In general, "smaller" means easier to understand, track and manage etc.
> Hence the "better" (or at least its "enabling": I *did* see early
> programs written in an OO lanaguage but made by one huge class with
> dozens of member variables.. but not lately, to say the truth :).

Smaller, at least to the size we humans can manage well, will
translate to BETTER. Too small isn't good. Too big isn't good.
We have to manage things on our own terms. Or, to quote a famous
fictional character, "A man's got to know his limitations."

>>If one considers a dynamic language like Smalltalk, where
>>there's no specific type-checking done, that reason for
>>having classes is only a small bit of the story - perhaps
>>an afterthought.
>
> No doubt. I find it nevertheless interesting because it's somewhat less
> obvious than other reasons. I remember "viewing" it for the first time
> when I was into lambda-calculus, continuations and denotational semantics
> in general - where the context is literally (and mathematically) carried
> around in a very compact form.

makes me think there's room for a good (functional OOPL) FOOPL
At least worth a look, wouldn't ya think?

>>I've seen procedural programs where a function has a parameter
>>list a mile long. I think sometimes OO was created to do away
>>with those.
>
> Yes, you just have one more place to put all that "context" which doesn't
> make sense globally, but is still shared by a good number of related
> methods.

But, the parameter list isn't really segmenting the global data
context in any permanent way. It's just for the duration of the
function's execution. No, OOPL classes segment on a permanent
basis and the part which flows from the algorithm through the
objects is very small (ideally). This may have originally appeared
to be a naming improvement, like modules before, but has actually
become something much more severe. Whether it's a real improvement
or a self-restraint beyond needs is unknown.

>>By "carrying" the context and function together there's
>>no need for all those long parameter lists. But, there is a slight
>>lessening of flexibility caused by the wall around the function.
>
> Yep. At the very least, the programmer must make an explicit effort to go
> past that wall to reach the external scope (and with some languages, he
> can't). Still, my experience's that it's price worth paying.

Time will tell.

I think we need more flexible use of things and I don't see
it (what I imagine) being available in most OOPLs. If we're
going to go towards 'how the programmer thinks' then we have
to allow objects to be utilized as the programmer would like,
rather than only in the narrowly ways they might have originally
been planned to be used. How this might be achieved without
retreating to C structs + functions isn't quite clear to me.
But, it seems clear to me there are ideas about how we might
move forward with our languages. So, I look forward to the
day when these improvements become available.

Patrick May

unread,
Jul 2, 2004, 4:34:13 AM7/2/04
to
"Mark S. Hathaway" <hath...@marshall.edu> writes:
> > > If one considers a dynamic language like Smalltalk, where
> > > there's no specific type-checking done, that reason for having
> > > classes is only a small bit of the story - perhaps an
> > > afterthought.
> >
> > No doubt. I find it nevertheless interesting because it's somewhat
> > less obvious than other reasons. I remember "viewing" it for the
> > first time when I was into lambda-calculus, continuations and
> > denotational semantics in general - where the context is literally
> > (and mathematically) carried around in a very compact form.
>
> makes me think there's room for a good (functional OOPL) FOOPL At
> least worth a look, wouldn't ya think?

http://www-2.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part5/faq-doc-0.html

The more I use Lisp, the more I realize how little the state of
the art in this industry has advanced in the past 40 years.

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc. | The experts in large scale distributed OO
| systems design and implementation.
p...@spe.com | (C++, Java, ObjectStore, Oracle, CORBA, UML)

Cristiano Sadun

unread,
Jul 2, 2004, 7:51:52 AM7/2/04
to
"Mark S. Hathaway" <hath...@marshall.edu> wrote in
news:40e4...@alpha.wvnet.edu:

> The compiled version might somehow manage execution code better,
> but there's no reason the OO source code we're getting used to
> would be the only way to get there. Note, I'm not suggesting an
> alternative at this point, just ruminating.

Perhaps it's a bit like Churchill tought of democracy - a not quite
perfect way, but so far not much better around.

Then, after all OO is just an evolution from a preceeding paradigm - the
procedural. That leaves the door open for both successive evolutions (and
we've had alrady COP and we're having AOP, for example) and simply
evolution from different, non-procedural roots.

> Come to think of it, what parts of current OO languages
> are clearly wrong or a problem?

Good question. In one sense, I don't see any problem: if you're good
enough (or your team's good enough) you can do everything. The problem's
that this can be said of C, COBOL or even assembler. :)

So perhaps a reformulation could be "what parts of the current OO
languages are clearly still making simple things too difficult, or too
easy to get wrong?"

Taken that way, the programming language debate can be just a "wicked
problem" - one where just stating the problem is a problem. :)

> Is our next language just like the current ones, but with
> even more power. Or, is it similar to current ones, but
> with some reigning in of side effects we hadn't expected
> when they (these OOPLs) were first created?

Perhaps simplification, rather than more power, is the main direction. Or
matching as closely as possible the way of thinking of *the* particular
programmer that's using the language in that moment. C++, come to think
of it, tries that a bit. Depending on who you are, you can use it as you
like. And it doesn't work much. Java's better at that, but still doesn't
*force* you to act properly.

Or maybe the solution is in compilers rather than languages. What of a
compiler able to examine your code rather than just translating it and
give *meaningful* suggestions (very much as people do here, and unlike
certain well-known software house "assistants")? "Hei, this is more or
less the same block, why don't you refactor it in a method"? "Hei, a
factory pattern would be perfect here, what do you think?". :-)

> Improved naming and code writing...trivial really, but useful.

Indeed.

> Smaller, at least to the size we humans can manage well, will
> translate to BETTER. Too small isn't good. Too big isn't good.

Good point.

> makes me think there's room for a good (functional OOPL) FOOPL
> At least worth a look, wouldn't ya think?

I think there are (there's at least an OO version of lisp around) but
I've never gained enough field experience with them, mainly for matters
of time and will. Yep, I too have the "programmer" syndrome. :)

Agreed on all the rest.

Jeff Brooks

unread,
Jul 2, 2004, 12:24:36 PM7/2/04
to
Robert C. Martin wrote:
> On Wed, 30 Jun 2004 23:25:49 -0400, Thomas Gagne
> <tga...@wide-open-west.com> wrote:
>>
>>Robert C. Martin wrote:
>>
>>>On Wed, 30 Jun 2004 11:43:52 +0100, "I spy" <s_ned...@yahoo.com>
>>>wrote:
>>>
>>>>OO is really targetted at managing architectural dependencies in fairly
>>>>large code bases (its interesting that it didn't really take off until code
>>>>got to a certain size that architecture became an issue),
>>>
>>>"targeted" is probably not the word I would use. I don't think the
>>>creators of OO were targeting anything. I think, for them, OO was a
>>>happy accident.
>>
>>Robert, you know better than that! Alan Kay wanted to do the most profound
>>thing he could as best as could be done. It wasn't an accident. It was
>>deliberate.
>
> Kay was not the originator of OO. That honor belongs to Kristen
> Nygaard and Ole-Johan Dahl. They were fiddling around with Algol in
> the mid '60s and came up with a language named Simula. This language
> influenced both Kay and Stroustrup.

Alan Kay is the originator of OO. He created the term OO but it was
later bastardized to mean "classes and objects" which is a subset of
what he envisioned.

"I invented the term Object-Oriented and I can tell you I did not have
C++ in mind!"
- Alan Kay

----- From: http://c2.com/cgi/wiki?HeInventedTheTerm
A lot of the developers and managers at Apple were gathered around
watching a presentation from someone about some "wonderful" new product
that would save the world. All through the presentation, he had been
stating that the product was "object-oriented" while he blathered on.

Finally, someone at the back of the room piped up:
"So, this product doesn't support inheritance, right?"
"that's right".
"And it doesn't support polymorphism, right?"
"that's right"
"And it doesn't support encapsulation, right?"
"that's correct".
"So, it doesn't seem to me like it's object-oriented".

To which the presenter huffily responded
"Well, who's to say what's object-oriented and what's not?"

At this point the person replied,
"I am. I'm Alan Kay and I invented the term."
-----

Jeff Brooks

Mark S. Hathaway

unread,
Jul 2, 2004, 12:49:55 PM7/2/04
to
Patrick May wrote:

>> "Mark S. Hathaway" <hath...@marshall.edu> writes:
>>
>>makes me think there's room for a good (functional OOPL) FOOPL At
>>least worth a look, wouldn't ya think?

> http://www-2.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part5/faq-doc-0.html
>
> The more I use Lisp, the more I realize how little the state of
> the art in this industry has advanced in the past 40 years.

That it hasn't become the standard should be a clue.
What do you think is wrong with it that so many people
ignore it?

It is loading more messages.
0 new messages