Wednesday, September 20, 2006

Design Patterns and Programming Language Design

Design and more Design...Patterns and Programming Languages

Mark Dominus has an interesting article about design patterns and programming language design.

In short, the thesis is made that a design pattern reflects a short coming of the programming language, or as the author puts it,”Patterns are signs of weakness in programming languages.” The speculation is what-if design patterns
had been popular in the 1960’s and 1970’s.

An interesting statement by the author is,”...the patterns should be used as signposts to the failures of the programming language. As in all programming, the identification of commonalities should be followed by an abstraction step in which the common parts are merged into a single solution.”

As I have designed a programming language, Mynx, the author’s article and commentary (even though it has a touch of bluster rather than objectivity) pointed out a design facet of programming language design. Namely, what features
become part of the programming language, and what features must be constructed by a developer in the programming language.

To think about the question, a specific, tangible feature of Mynx needs to be
considered in relation to a design pattern.

One feature in a way in Mynx has a corresponding design pattern, static classes and the singleton design pattern.

A singleton in short practice, is a creation design pattern that allows only one instances of an object exist, hence single. Any time the method used to create or get the instance is accessed, it returns the reference/pointer to that single instance.

A Mynx static class is a class that is never instantiated, but always exists -- there is only one version of it, hence static. All class elements are also static, and the only classes that can be inherited are static.

Comparing code for a static class and a default class that implements the singleton design pattern with the same method “doIt” in the class:


static class Static is

     public singular doIt is
         null;
     end doIt;

end class;

default class SingletonXXX is

     private static XXX single to default;

     private construct is to null;

     public constant XXX getInstance is
         return single;
     end getInstance;

     public constant doIt is
         null;
     end doIt;

end class;

The static class is quick and easy to code, whereas the singleton class requires more overhead, the constructor to create an instance, a static attribute for the single instance, and the access method to get the reference to the instance.

At first glance, it would seem that Mark Dominus has something profound...but (and you knew this was coming...) there is one other point to consider.

Making the leap from singleton design pattern is equivalent to static class overlooks the fact that a singleton can have state -- memory, whereas the static class does not, a static class is stateless. The static attributes can retain memory, but the static class and static methods do not.

So does this mean static attribute is equivalent to singleton? No. A singleton uses a static attribute which has state, and the methods are created to control creation and access to the static attribute. So then, why not just use a static attribute? That opens up the can of worms about encapsulation. Violating one object-oriented principle in order to integrate a design pattern into the language is to use a phrase robbing Peter to pay Paul (and vice-versa).

What does it mean? The conclusion is that saying for a design pattern there is a language feature is an over-simplification, and design patterns use features of the object-oriented paradigm like encapsulation, polymorphism, method overloading to create constructs with desirable features. Saying a design pattern is indicative of a weakness in the programming language is to say eliminate all the features of the object-oriented paradigm and provide nothing but design patterns as features of the language. Then it is a question of power in terms of one kind of language creating features in the other. Can an object-oriented language create design patterns (yes) versus can a language of nothing but design patterns create object-oriented features like encapsulation, polymorphism, inheritance...I’d say no without some difficulty.

To use a metaphor, design patterns and object-oriented programming languages are like plastics to chemistry, the laws of chemistry allow plastics which are synthetic materials to be made, but does that mean there’s a flaw in nature because plastics do not naturally occur?

But there is something interesting that design patterns and programming languages can have...but I'll save that for another blog post about a possible future feature of Mynx.

Labels: ,

Saturday, September 16, 2006

Multiple-Inheritance and Inheritance...Again!

In writing about inheritance in Mynx, an interesting point about C++ is that multiple disjoint inheritance is possible in C++ (but not Java or C#) but the language specification/compilers do not enforce or check for multiple disjoint inheritance. (It would be an interesting project to write a Perl/Python/Unix shell script to enforce, check for disjoint multiple inheritance.)

However C++ does have the mechanisms in the language to handle unrestricted multiple inheritance, which would be unnecessary if the programming language had multiple disjoint inheritance.

Inheritance is a powerful object-oriented paradigm feature, but can be abused and misused. In Java for example, it can be abused (and not just multiple-inheritance) creating the pseudo-type definition antipattern.

But, like a sharp knife, light saber, or phaser, a powerful feature can be abused, inheritance in software using object-oriented programming languages.

Inheritance is powerful, but it seems multiple inheritance is the square of the power of inheritance.

C++ has unrestricted multiple inheritance, Mynx multiple disjoint inheritance, and Java/C# single-inheritance...going from x^2 to x^c where c > 1, to x^1.

Labels: , ,

Thursday, September 07, 2006

Multiple Inheritance in Mynx Part Deux

Multiple inheritance is fraught with peril, how does Mynx handle the features of multiple inheritance?

Simple - by not dealing with them. Huh? Or to paraphrase an old maxim:

"If you open a can of worms, you'll need a bigger can." To avoid the problem do not create it...Mynx might use the infamous can of worms, but it does not open it.

Multiple inheritance in C++ requires either dis-ambiguation to avoid a vague reference in a super-class, or specifying a class as virtual to avoid repeated inheritance. Eiffel allows specifying which super-class is selected.

The overall problem is ambiguity, with two classes with overlapping methods, or with overlappig super-classes, a sub-class either has ambiguity or repeated inheritance. So Mynx insists that inheritance as multiple is disjoint (a term borrowed from set theory) so that super-classes do not overlap in method names/signatures, or in super-classes. Hence the term, multiple-disjoint inheritance.

For example, repeated inheritance:

class A as null is
     public construct is to null;
     public void doh is to null;
end class;

class B as A is
     public construct is to null;
     public void duh is to null;
end class;

class C as A is
     public construct is to null;
     public void dah is to null;
end class;

class D as A,B is
     public construct is to null;
     public void deh is to null;
end class;


Class D is multiply disjoint from classes B and C, but both classes B, C are
sub-classes of A -- repeated inheritance. Illustrating using arrow notation:


A->0 (use zero for null super-class)

B->A

C->A

D->B->A
D->C->A


Now the problem is very plain to see--class D has repeated inheritance of class
A through the super-classes B, C.

The problem would be noted as an external semantic error of repeated inheritance
of a common ancestor super-class A. The information about a class, and its
super-classes is stored in a MOXI file, and XML file that contains information
about a class--including all super-classes, including the class's super-classes.

To work in Mynx, the classes must be rewritten as:

class A as null is
     public construct is to null;
     public void doh is to null;
end class;

class B as null is
     public construct is to null;
     public void duh is to null;
end class;

class C as null is
     public construct is to null;
     public void dah is to null;
end class;

class D as A,B,C is
     public construct is to null;
     public void deh is to null;
end class;


Now the multiple inheritance is truely disjoint, no problems with repeated inheritance, but the classes used must be designed intentionally with the goal of multiple inheritance in mind.

Using arrow notation:

A->0 (use zero for null super-class)

B->0

C->0

D->A->0
D->B->0
D->C->0


The common super-class is 0 or null -- which is not an actual super-class (although for consistency it is considered a class).

In the triumvirate of C++, Java, and C# one of the features of C++ that I really like (and didn't really realize...one of the benefits of designing your own programming language, you find features in existing languages you like) is that C++ does not have an implicit hierarchy of classes.

Both Java and C# both have "Object" as the default, defacto super-class. With C++ there is the option of using a class hierarchy...in terms of more powerful or flexible, C++ you do not have to use a class hierarchy, but in both Java and C# you cannot unuse a super-class (you can with an interface...but not all classes...). Thus the C++ flexibility of choice for a super-class object is a powerful feature.

Mynx uses null inheritance like C++'s flexibility of not using a super-class. The flexibility is necessary for multiple-disjoint inheritance. Forcing a super-class of "Object" or "superObject" class will always create both repeated inheritance and name ambiguity.

So a very little recognized feature of C++ is in fact a very powerful feature for multiple-inheritance. Mynx borrows this from C++, and the notion that if a software developer does not want to use a base super-class, it is up to them...particularly if the intent is a class for use in multiple inheritance.

C# is much like C++ (and C# is not a simple Java-clone as some Microsoft detractors have asserted in my humble opinion...) but C# does miss the boat in that the ability to choose a super-class or not. (On the other hand, C# does allow for delegation which is useful for achieving multiple inheritance like features...). Of course, both Java and C# have avoid the can of worms by throwing away the can.

Labels: , ,

Friday, September 01, 2006

Multiple Inheritance is Evil/Bad...NOT!!!

The Mynx language has 3-types of inheritance:

The 0th element is, strictly speaking, not a type of inheritance, but it is an option for a class, so is included to be consistent and complete.
  1. nothing or null inheritance (class is standalone like C++ no required super-class like C# or Java)

  2. single inheritance

  3. virtual inheritance (inherit multiple virtual classes, like inheriting multiple interfaces in C# or Java)

  4. multiple inheritance
Gasp! Mynx uses multiple inheritance--which is supposed to be "evil" or "bad".

Multiple inheritance is often taught as bad, evil, or somehow a negative thing in the world of object-oriented programming. C++ has (infamously) supported multiple inheritance, as do other languages such as Eiffel, and Python.

Mynx has multiple inheritance, but it has a different kind of multiple inheritance to avoid some of the problematic aspects that come with multiple inheritance.

Name Ambiguity

In C++ multiple inheritance, an aspect of multiple inheritance that can be problematic is name ambiguity; a method is multiply inherited so there is ambiguity in which one to invoke by a name. In C++ the code for name ambiguity is:

class A { virtual void f(); };
class B { virtual void f(); };
class C : A , B { virtual void f(); };

int main()
{
     C* c_ptr = new C;

     c_ptr->f(); //which f() is invoked?

     return 0;
}

The name ambiguity is which method f() is invoked in the call in the main() method.

Deadly Diamond

The classic problem of multiple inheritance is the diamond problem or the "deadly diamond"...when a class inherits from multiple classes with a common ancestor or super-class. This can lead to name ambiguity (as illustrated without the deadly diamond).

In C++, the code for multiple inheritance that creates the deadly diamond is:

class A { virtual void f(); };
class B : A { virtual void f(); };
class C : A { virtual void f(); };
class D : B, C { virtual void f(); };

int main()
{
     D* d_ptr = new D;

     d_ptr->f(); //d_ptr has two instances of class A

     return 0;
}

The problem is that the deadly diamond is repeated inheritance the base class A is inherited multiple times. This can lead to erratic or unpredictable behavior of any class D object instances.

So two "gotchas" that are the difficult aspects of multiple inheritance are:
  1. Name Ambiguity
  2. Repeated Inheritance
C++ (and this is one reason you either love the language or hate it...) has a mechanism to avoid the problems of multiple inheritance, but if a software developer is not careful it is easy to blunder badly. C++ has what I like to term "unrestricted" multiple inheritance...it is up to the class designer to be sure they know what they're doing...and given the bad reputation of multiple inheritance, that takes a great deal of skill and work. (Another reason to hate or love C++...either sink or swim in the language...)

Two other languages have multiple inheritance, including Eiffel, and Python. Both put constraints on the level of multiple inheritance.

Eiffel requires a multiple inherited class to select which one to use. Python uses a depth-first left to right to search for name resolution -- but Python supports only a limited form of multiple inheritance.

Multiple inheritance is so fraught with danger, why does Mynx include it as one of the language features? Simple, Mynx is not trying to constrain the software developer's choices, and multiple inheritance can be useful at times...like an esoteric tool that is infrequently used, you really are glad to have it when the need arises...and as a language designer, I can not foresee that such a need would never arise. Mynx implements multiple inheritance differently...but I'll discuss that in another blog entry.

For those who fear or contend multiple inheritance is evil or bad, the answer is to simply don't use it if you think it is evil...(remember the classic doctor joke? Doctor it hurts when I do this...The doctor says--then don't do it...nyuck...nyuck...) and remember that evil spelled backward is "live"...multiple inheritance in the eye of the beholder...but as the language designer I leave the choice to the Mynx developer using the language.
Website Spy Software