the OO metaphor

Ulf Wiger <>
Fri Dec 1 11:08:30 CET 2000


On Thu, 30 Nov 2000, Vlad Dumitrescu wrote:

>$inherit_api (or something similar) would be a nice and clean way to
>handle this issue.

Perhaps, in response to Bjarnes post, it could be called $reuse_api()
or something, to avoid getting our feet stuck in the OO mud.


>On the other hand, interfaces that are shared like this create also
>problems: for example, what happens if an interface that is extended
>by many other has to be changed in a non-compatible way? There are
>solutions, of course - the point is that there may be more things to
>think about than one sees first...

I think we have these same problems today, and then some.
Of course, one significant change would be that it would become easier
to reuse the API of other modules, which would probably make
programmers use it more.

But I've never been a fan of the "let's make this difficult so that
people will stay away from it" philosophy. (:

Today, you have two options:

1. Copy and paste the code from one module to another
   - obvious problem: if you find a bug in the implementation, you
     have to change the code in multiple places

2. Write a function, f() -> OtherMod:f()
   - problem: if the implementation changes incompatibly in OtherMod,
     your API will break.
   - problem: if functions are added to OtherMod, you must also
     change your module (if they were functions that you also need
     to support
   - advantage: code reuse is explicit

With a function like $reuse_api(),
- code reuse is still explicit, but perhaps less so
- you can opt to have functions dynamically added to your API,
  by specifying that "all functions in API M are also part of 
  this API.
- Incompatible changes in a reused API will break other APIs, but
  this is hard to solve without resorting to (1): copy and paste.

One significant disadvantage, though, would be that we'd lose the
ability to easily track whether interfaces have changed, as they
could change "indirectly". At AXD 301, we have a convention to keep
separate interface modules, which only contain "pointers" to
implementation functions in other modules. The main purpose of this is
to highlight the API, and make it easy to see if it has changed (the
revision of the API module changes.)

But of course, the two approaches can coexist. Dynamic APIs would be
useful if you write generic dispatch functions or behaviours.

Personally, I really dislike the type of inheritance that e.g. Java
has, where you have to chase around in several code modules to find
out what a method really does. 

I think programs should be expressive and explicit to the greatest
extent possible. For example, one should always think twice before
using constructs like apply(M,F,A), or Process =
OtherMod:lookup_process_name(...), Process ! Msg. I've come across it
every now and then in various programs, and it almost always makes
fast code browsing nearly impossible. Sometimes, these constructs are
invaluable, but in the vast majority of cases, you can do the same
thing explicitly without losing anything.

One final point (I may be shooting down my own suggestions, but then
so be it): Anytime you add something to a programming language, you
must think carefully about wether it:

- will make the language harder to learn
- will shift the focus of the language

A good language should _encourage_ programmers to write code in an
elegant fashion. For example, whether or not one can employ functional
programming in Java is really quite uninteresting: the important point
is that Java the language doesn't encourage you to do so.

I think that, to a great extent, Erlang does encourage people to write
pretty good programs. This is one of its greates strengths.

/Uffe
-- 
Ulf Wiger                                    tfn: +46  8 719 81 95
Senior System Architect                      mob: +46 70 519 81 95
Strategic Product & System Management    ATM Multiservice Networks
Data Backbone & Optical Services Division      Ericsson Telecom AB




More information about the erlang-questions mailing list