Sunday, 14 February 2010

Do you GoF - the belated anniversary and the ladder

Last year we had the 15th (or so?) anniversary of the seminal "Gang of Four" book. Is it that old already? So maybe discussing the design patterns is all an old and boring stuff now? Well, shame on me, I wanted to write up my ideas on that matter for such a long time that I run the risk of them beeing irrelevant. But on the other side it's a kind of unfinished business for me, and I have a to kind of close it up.

Some time ago I wondered - why didn't I use the design patterns that much in my programming and design work? I came to the conclusion then, that the design patterns are useful as a common vocabulary as to speak about designs, but then some new ideas surfaced in my mind. By the way, why should I use a pattern vocabulary if I don't use any patterns in my designs?

1. Ideas from chess and math

If you're playing chess (need a Wikipedia link here? ;-) you are accustomed to seeing the board in patterns: check-mate patterns it is! You try to imagine what kind of a check-mate setup could be possible in a given situation, and then work towards that by moving your pieces and trying to chase away your opponent's pieces as to complete the pattern you have in your mind. I must admit that I never had this feeling when writing software. Some pattern in my mind which is the solution for some design problem? Nope.

Read the "Refactoring to Patterns" book by Joshua Kerievsky? When I first heard of the book I though he struck the right idea: only use patterns to refactor code which is a mess. But then when actually reading the book, it was rather a feeling (in most cases) of doing something wrong to the code, well, like overengineering it! So the book didn't reconcile me with patterns too, as it didn't give me the chess-like feeling of a pattern just matching a given situation.

The other problem with patterns is their presentation. This overly formal template with "Forces" (why not just problems?), "Intent", "Consequences", etc, etc... This makes me think about "The mathematicians lament"* - where a matematician reproaches his fellow scientists of over-formalization of mathematics with the effect of its incomprehensibility. What he is saying is basically the following: yes we need the formalism, but only in some very difficult cases where our intuitions don't work. But not in every and one case: "nobody's dying here!"*, you can relax a bit!

It's the same with patterns: the stern formality of presentation is both somehow comical and making the contents rather indigestible, and an dry, uninspiring read. I can only say, relax, we are not deliberating about the meaninig of infinity like Cantor did! We are just describing some not so complicated techniques of object composition! Could you stop to be so pompous?

2. Dreyfus et al.

Do you know the Dreyfus model of knowledge acquisition**? It defines several phases in learning a specific skill: beginner, advanced beginner, competent, proficient and expert. Beginners need rules and recipies, competents can continue learning on their own, proficients and experts see the big picture and fly by the seat of his pants.


Where do the design patterns fit in this scheme? Well, at the beginner level they aren't useful, as they are not "step by step" recipies. On the other side, for the proficients and experts, they are some kind of rules, and experts do not like rules and recipies by definition!

I personally think that patterns appeal rather to the lower ranges of the skill spectrum. Did you see the hopelessly overengineered software full of design patterns written by the beginners? I've seen it only too often!

So maybe they are for the competent? And the usage by competent and proficient users? Let me tell you a little story here. It's not entirely true that I don't use patterns! Lately, I thought that I could warrant the use of the visitor pattern in my current product, as to extract the reporting aspect out of several content managing classes. Well, it has a kind of worked at first, but now, as this whole aspect has to be redesigned, I noticed that this design is rather unintuitive and I cannot simplify the reporting without dumping visitor first. Ok, experiment failed, but my initial problem was that I didn't really search for a solution of my problem, but rather stopped at the point where I found the (as I thought then) matching design pattern! But I didn't think it trough as thoroughly as I should!

3. Summing up

So maybe the thing with patterns is that they are like the "Wittgenstein's Ladder"? You know, what he said in his "Tractatus Logico-Philosophicus" (I cite from memory):

...this book is like a ladder, use it, but then throw it away.
Isn't it the same with patterns? Use them to expand your experience, but don't use them in your software! And as to make the discussion complete, let us state a completely different point of view, a Lisper's critique***:
When I see patterns in my programs, I consider it a sign of trouble. The shape of a program should reflect only the problem it needs to solve. Any other regularity in the code is a sign, to me at least, that I'm using abstractions that aren't powerful enough-- often that I'm generating by hand the expansions of some macro that I need to write.

This is the typical smug Lisp programmer assertion, as they mean that all other languages will in limes converge to Lisp, but newly I tend to think along the lines of the Lispers: the design patterns are a fix for lacking feature in language A, which you know from language B. But as we cannot change the language in most cases, and we are doing OO in the mainstream, just mind the ladder parable!

Update (June 2010): There's another explanation which I didn't think of before. I came across that when reading some programming book (which I cannot come up with now, sorry for the author!). Recall the mid 90-ties: it was the time of the "object craze", everybody wanted to be part of OO. But nobody really understood OO, and as the book went "Stroustrup gave us the C++ but he didn't tell us how to use it"! Her come the patterns, a kind of missing OO manual! This would explain my feelin that half of them was trivial (or not so difficult to figure them up by yourself) and the other half was implemeting language features missing from C++. Very sober diagnose, but at the moment it's my favourite.

---
* Paul Lockhart, "A Mathematician’s Lament", www.maa.org/devlin/LockhartsLament.pdf

** I found it in the book of Andy Hunt, "Pragmatic Thinking and Learning", Pragmatic Bookshelf, Oct. 2008, but here's a blog post link, and here another one

*** Paul Graham, "Revenge of the Nerds", http://paulgraham.com/icad.html

Monday, 21 December 2009

Local language trends 2009

I just had a look on the statistics pages on our local IT freelancer website (http://www.freelancermap.de/) and found the results pretty interesting. First let's have a look at the languages which are most popular in the freelance projects. The picture below shows the languages, the supply of programmers (the blue bar) and the demand in projects (the red bar).

As it seems, here in Germany there are only two serious languages: C/C++ and Java. Well, ok, Visual Basic and C# are sough after rather strongly (red bars), but there seems to be too little supply. Is that the fear of a vendor lock-in or is it just because Microsoft is considered evil that the programmers don't like .NET? The same case of too little supply for PHP, but here I must mention that the hourly rates for PHP tend to be rather low - PHP still considered a hacker language?


And now look at the last but one language with a longwinded German name I won't retype here (too lazy). In fact it's not a language of its own, but rather denotes "all the other ones in there", which includes everything fancy (or just plain old). You see there is too much supply, the IT managers seem to be more conservative than programmers, no surprise here.

Which leaves us with C/C++ and Java. Java is unmistakeably the 500 pound gorilla here, but it's hopelessly over-supplied (blue bar)! For C/C++ the situation isn't so dramatic, and I'm glad I specialize in C++!

The proposed course of action here: go away from Java (or well, from everything else for that matter) and start on .NET!

Now the overview of technologies in the freelancer projects:

Software development comes first (still a little place for more work - red bar!), then system management (plus "service and support"), however the suply here is much too big (blue bar)! It's just as bad as for SAP programming - in the past the eternal cash cow with ridiculously high hourly wages, now it's a real "problem child" - the market seems to be breaking down. Banking crisis anyone? For Web development and "graphics, content and media" there's much too much demand, just like in the PHP case above. Then the ominous field of "IT consulting", where I don't have any idea what it is, sorry, no comments there :-/. One interesting field is "Executive consulting" with so much demand and so little supply, maybe everyone is just too shy to position theirself in that niche?

The proposed course of action here
: either stay with software development or move into "Executive consulting"!

Having said that: Merry Christmas you all!

Wednesday, 16 December 2009

Even more new C++ features!

Hi everybody! As I had a look on the new C++ proposal the last time , I found many small interesting things apart form the big, important features. But this was only a first look. Recently I had another look there (and at the C++0x FAQ* by Bjarne Stroustrup as well) and discovered even more interesting crittures. So what did I miss?

1. Some Syntax

First of all the new function definition syntax! Now I can write something like*:

  using PF [](double) -> void;
along the lines of lambda function definition! Well, that's definitely a treat, what a relief from

  typedef void (*PF) (double);

To be honest, I don't know if I've got the last one right, I have always to look thes syntax up or copy and paste from my other code! The [] notation can be generally used to say to the compiler that "the function type will be specified later"! Thusly we can write the following when usign embedded type like List::Link

  [] List::erase(Link* l) -> Link* { ... } ;
We postpone the return type definition utill we have entered the scope of List, and thus no scope specifier is needed!

I liked this notation (it makes the code look a little Groovy-like), but alas, it seems that not everyone does so, as the related "auto arrow" notation proposal was rejected recently**! What is auto-arrow? Look at that***:

  auto f() -> int;
typedef auto PF() -> int;
the first one is a function from void to int, and the second one is a function type definition for the same signature. Looks good enough, but consider this one:

  auto *pf(auto *p() -> int) -> auto *()->int;
I don't even want to discuss what it means, if you are curious look it up in ***! So after that proposal was justly rejected, I'm a little afraid of the fate of the [] notation - is it the next one to be scrutinized? I hope not!

2. Initalization and initializers

I though I've understood the new initalizer notation, but I was surprized how ubiquitous it became! At first I though it would be only used in assignment like

  vector<int> xs = {1, 2, 3 };
Not so, nowadays you can use it (i.e. the new {} notation) everywhere, even instead of classic parentheses!

  X x{a};
f({a}); // initializes a temporary
X* p = new X{a};
This all does look pretty strange to me, and to be honest I don't like it that much, but on the other side you can use it to avoid verbosity with pretty good results:

  map1.insert({a, b}); // sic!
The other improvement with initialization is that we can initialize the string and integer class members directly in the definition of the class!

  class X
{
int a = 7;
string s{"abcd"}; // new syntax!
};
I can only say AT LAST and amen!!!

Belonging to the "initialization" block of features, we must mention the access to the inherited constructors (in addition to the also new feature of delegating constructors, i.e. constructors which can be invoked of another constructors of the same class):

  class A { public: A(){} };
class B : public A
{
using A::A; // imports all the A's constructors into current scope!
};
  // now this is possible:
B b;
At this place I'd like to mention another related feature: disallowing copy and assignment operators. You can write for example:

  X& operator= (const& X) = delete;
to disallow it! Well, if I consider that Google even has a macro exaclty for that reason (DISALLOW_COPY_AND_ASSIGN(), see here) and that I used an UML tool to generate the private version of it for my every class I think that the default-generating them was a bad language design idea! If we want a copy semantics we'd better tell the compiler so! Hindsight is 20/20.

3. Threading etc.

Of course thread, mutex, condition variables and atomics are there as basic support (as expected). On the higher level we have futures and a packaged_task class, which wraps features for simpler usage. Moreover, Bjarne does promise that an async task launcher (logically named async) will be included in C++0x as well. Then we could launch tasks simply like that:
  auto f1{async(funcX(100))};
auto f2{async(funcX(200))};
  return f1.get() + f2.get(); // waits on both futures
If he's right it would be very nice!

As GC is connected to multithreading in an intimate way (at least in my eyes, sholud blog about it some time soon!), I must state here that the GC is still missing!

But not entirely, we've got some minimal support for third party garbage collectors in there (20.8.13.7 Pointer safety). It defines what a "safely drived" (i.e reacheable) or an "disgused" pointer is (3.7.4.3 Safely-derived pointers) and lets the programmer specify where such pointers can/cannot be found with declare_reachable()/declare_no_pointers() functions.

One thing that struck me however in the threading library classes is the flexibility of interfaces. Take the std::thread's constructor for example. You can use it like that ****:
  void hello_func() { ... }
// say hello
std::thread t{hello_func};
or like that, using a functor:
  class Greeting
{
public:
explicit Greeting(std::string const& message) { ... }
void operator()() const { ... }
void greet(std::string const& message) const { ... }
};
// say goodbye
std::thread t(Greeting("goodbye"));
or currying the thread function with std::bind:
  void greeting_func(std::string const& message) { ... }
std::thread t(std::bind(greeting_func, "hi!"));
or without std::bind:
  std::thread t(greeting_func, "hi!");
or without std::bind and with more arguments:
  void write_sum(int x, int y){ ... }
std::thread t(write_sum, 123, 456);
or using the member function pointer
  Greeting x;
std::thread t(&Greeting::greet, &x, "greet");

// or by a smart pointer
std::shared_ptr<Greeting> ptr(new Greeting);
std::thread t1(&Greeting::greet, ptr, "hello");

// or by reference
std::thread t2(std::ref(x));

// or directly!
std::thread t2(x);
See, you don't need to worry about the initalization, the new constructs will just take anything you throw at it!

4. Miscellanea

First the variadic templates. What a name for templates with viariable number of arguments! I guess it's an interpolation of the "dyadic" concept which just means "of two arguments" :-). But seriously, we can writhe things like
  template<typename Head, typename... Tail>
doing recursion and typematching like in Clojure or Haskell ;-) Well a kind of, but it looks like that at least. Look at the n-tuple definition using variadic templates in Bjarne's FAQ*.

Further, the new and improved enums (which are class based now) can be now forward defined ! But I'm doing this all the time with C++ Visual Studio 2005! Ouch...

No for the geeky ones: we have user defined literals! You can define new literal types using the following new operator type: operator""() (plus constexpr!), for example

  "abc"s; // s: string literal
2i; // i: imaginary literal
For details have a look at Bjarne's FAQ*. NIce feature, but will I use it? It is readable for the maintainer? We'll see.

The next 2 features look to me as if they came straight from Python. First the raw strings:

  string s = R"[ahjh/?=(%/$§%§%\w\\w///]";
Why not just R"..."? Dunno. Next the foreach variant of the old for() loop.Together with initilizers we can now have some Python feeling in C++:

  vector<string> xs = {"aba", "bab", "aab" };
for(auto x:xs) cout << x; // x:xs looks even a little Haskell-like ;-))

So there are many new things, some of them making C++ look like entirely another language. No I wonder - will the C++ programmers use it, or will they stuck to the old, but known evil (like the old function definition syntax)?

---

*Bjarne's "C++0x - the next ISO C++ standard", http://www2.research.att.com/~bs/C++0xFAQ.html

** Danny Kalev: "The Rejection of the Unified Function Syntax Proposal", http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=460

*** Daveed Vandevoorde: "The Syntax of auto Declarations", http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2337.pdf

**** for completness' sake, the examples are partially taken from: http://www.justsoftwaresolutions.co.uk/threading/multithreading-in-c++0x-part-1-starting-threads.html


Tuesday, 24 November 2009

More about Java Closures

Surprize, surprize! Hear, hear!
One year ago, Mark Reinhold, Principal Engineer at Sun Microsystems, announced At the Devoxx conference in Antwerp, Belgium that the next major release of Java, JDK 7, would not include closures. At the same conference this year, however, Reinhold announced in a surprise turn around the Java would be getting closures after all in JDK 7.*

More specifically, they adopt the BGGA proposal (look here) but without the non-local return (look here) and control invocation statements. This leaves Java without any destructor or C# style using statements support!

What can I say? I can only reinstate what I said in my previous post: comparing to the development of the C# language (look here ** for an interesting inteview about LINQ and its supporting language features) the Java language looks increasingly mouldy (ouch!!!).

But maybe I'm mistaken? maybe there will be some support for modern ressource management in Java but it's decoupled from the closure proposal? Let's hope so.

Update: well, I didn't hope in vain, there will be a feature for this: Automatic Ressource Management (see here)!!! Moreover, we'll got a little bit of type inference for the right hand generic expressions with new (as Google Collections provides it) with a "diamond" operator (?) <>, and strings in the switch statement (as in Groovy). All in all you cannot complain, I'd say, and some bloggers (ehm...) shouldn't be too quick to bash Java 7!

--
* I found the news here: http://www.artima.com/forums/flat.jsp?forum=276&thread=274496
** http://www.infoq.com/interviews/LINQ-Erik-Meijer, BTW I found an interesting quote of general interest there:

Actually, if you look at where I'm going, I'm getting more and more into old school object orientation with interfaces and so on, going away from functional programming. If you are passing a high order function you are passing one thing, one closure. If you're passing an interface or a class, you are passing many because you are passing a whole V table. These can all be recursive and so on. I'm rediscovering object oriented programming and I feel that maybe I wasted some of my time doing functional programming and missed out on objects.

You see, it's not only the functional programminch which is gonna be the Big Next Thing! I think that we cannot just condemn OO and go all for the functional. OO has its merits when structuring code, and a hybrid OO/functional approach seems to be a good thing to me!

Wednesday, 11 November 2009

Songs in code

Won't explain what they are, because it's obvious. These two made me laugh:

Bob Marley's (and Groovy's):
  4.times{
!woman == !cry
}
and REM's (and SQL's):
  DROP TABLE MyReligion
but normally they are boring, uninspired or plainly wrong, like this one:
  while(young)
{} // loops forever
Come on, the whole thing is that young is a volatile variable, which will somehow, sometimes be set to false! ;-)

Friday, 30 October 2009

Java's Closures Debate for C++ Eyes


Years ago Sun described Microsoft's delegate extension proposal for Java as:

Many of the advantages claimed for Visual J++ delegates -- type safety, object orientation, and ease of component interconnection -- are simply consequences of the security or flexibility of the Java object model.
....
Bound method references are simply unnecessary. They are not part of the Java programming language, and are thus not accepted by compliant compilers. Moreover, they detract from the simplicity and unity of the Java language.*

blah, blah, blah, marketing drivel! I don't know what is more annoying here: 1. the object-oriented orthodoxy, or 2. the complacency that "we know it all better! Be that as it may, but now James Gosling (Mr Java himself) says he'd always wanted closures instead of anonymous inner classes in Java, and there is not one, but whole 3 (!!!) proposals how to include functions as first class citiciens of the Java language! So much for the "simply unnessary" argument...

And there is considerable controversy around the very idea of closures, somehow similiar to the C++ debate around Concepts we discuseed recently, deeming it unnecessary and "too complicated". As we are lucky to get lambda functions in C++0x and don't complain the least, the debate in Java community made me curious. Come on, why not to have closures? Even C# has some!

So what is a closure? For the sake of this blog entry it is something like a lambda function in C++ (or Python or Groovy), i.e. an anonymous, freestanding function:

  auto print = [] (int x) { cout << x; }
Now let's do it in Java.

1. Proposals

So let's have a look at the three proposals.**

a) BGGA (Bracha, Gafter, Gosling, Ahé)

This is the most ambitious proposal. It introduces a new type into the language: a function type, and a totally new notation for it. This notation remainds me of Haskell's or of the lambda calculus types.

{T => U} for a function from T to U
{T => U => V} (or is it {T,U => V}?) for a function from T and U to V
I think this notation is one of the purposes why many in the Javaland doesn't like this proposal a bit. The second one will be surely the nonlocal control statements (returns, breaks etc). Come again, non-what? Well, it means that for example the return statement doesn't return from the closure but from the scope which invoked the closure! They don't bind to the closure but to the environment! Why should that be good for? Wait till next section for expanation, dear reader.

An usage example:
  {Integer => void} print = { Integer x => System.out.println(x); }
b) CICE (Concise Instance Creation Expressions)

This is the simplest of the three proposals. Basically it's only a syntactic sugar for defining anonymous classes on the run, nothing more. No first class functions! No obscure functional programming theory!

An usage example:
  public interface IPrint { public void invoke(Integer x);} // exacltly 1 method!
IPrint print = IPrint(Integer x) { System.out.println(x); }
It's the simplest of the proposals, but for my mind, the most annoying one: you have always to refer back to some interface definition, and it sucks!

c) FCM (First Class Methods)

This is a kind of middle ground between the previous two: it introduces first class functions, but doesen't have the nonlocal binding for closures return statement and the irritatinmg lambda-type notation.

An usage example:
  #(void(Integer)) print = #(Integer x) { System.out.println(x); }
From all the three syntactically I like the BGGA proposal the best, as you can just write your code in a familiar code-block manner, without the FCM's hash or CICE's interface tag.

2. The Debate

To put it mildly, sometimes I find the debate somehow childish. Here the typical arguments:***

pro: If the don't implement closures, I'll never code any line of Java an will go to Scala
con: If they implement the closures, I'll just break down and cry... I cannot change to any other language, but I'll hate you all for that!
Come on people! It's just a language feature! And you don't have to use it at all if you don't like it. Beside this, it's not the developers that choose languages, it's the managers! If they can be convinced that a language offers some substantial benefits, it will be adopted. But not because you like Scala or something else better!

Will the closures make Java too complicated? Would they really

"...complicate the language beyond normal usability: mainstream programmers will turn away from Java, so the argument goes, and move on to simpler programming languages
...
Java will turn into a guru language used only by experts in niche areas
"**?

So tell me which the simpler languages for the JVM are! I can see none (nonscripting one) which would be simpler. Guru language? Are you kidding me? The closures are an attempt to make Java less verbose, so everyone should be happy. So why the fear?

One (non PC) answer might be, that the "too complicated" camp is perfectly happy with the language as it is now, doesn't mind the lack of elegance, and don't want learn new mechanisms. And maybe there is some point where there are to much mechanisms (or paradigms) in the language? Me, as a C++ guy, I'm accustomed to the "multiparadigm design", as C++ is a real behemot in that respect. I just try not to think about the mechanisms I'm not using now.

Maybe in Javaland this isn't so simple, as the programmers were lectured for years that there is only one paradigm in the world: the object oriented one. This would explain why some people think that the addition of generics stressed the complexity of language to the limits (the other explanation is the design choices for backward compatibility, in particular the wildcards).
So it seems to be either the the irritation caused the generics or the unusual nonlocal returns in BGGA which provoked the strong feelings, dont you think?

3. Discussion


But let's get more technical: why do we need closures in Java? The answer is probably: because Ruby has got it! The Java community seems still to be in a collective Ruby trauma, and emulating Ruby features is a good enough reason in itself. As they used to say behind the Iron Curtain: to learn form Ruby is to learn how to win! So now, just as in Ruby (or Groovy and C# for that count) we'll be able to write in Java:

  Utils.forEach(names, { Integer x => System.out.println(x); }); // BGGA

So, that's kind what we've always had in C++ with STL and lambda libraries.

But that's not all there is! In each of the three above proposals there is a second part, which allows some kind of finer-grained resource management, i.e. a kind of "destructors for the modern times". I can only say "finally", because Java's resource management is just a big pain in the rear.

BGGA tries to achieve this goal by nonlocal control statements mentioned above, which will then allow to implement the "execute around" pattern as so called "control abstractions"** , but are somehow not very intuitive. In the BGGA proposal the keyword this will be lexically bound and will automatically refer to an instance of the enclosing type in which the closure is defined. For me, Groovy solves the problem of nonlocal bindings somehow clearer - introducing two members for a closure: owner (refering to the enclosing object) and delegate (defining the lexical binding). In tis way wee can always explicitely say what type of lexical binding we need, the default value of delegate being owner!

The other proposals try to address the same question as well: CICE by ARM (Automatic Resource Management Blocks - a special type of block where a dispose method will be automatically applied when leaving it) and FCM by JCA (Java Control Abstractions - this one is more like the "execute around" pattern mentioned above, and requires nonlocal lexical bindings as BGGA does).

At this point let us try to draw some conclusions.

Firstly: with C# having the lambdas in its 3.0 version****, and C++0x having lambdas and the auto specifier, leaving closures out of Java 7 would let Java looking pretty old in comparison!

But don't despair, there is a library solution out there (http://code.google.com/p/lambdaj/). Maybe a library solution will be suffiecient in this case? I don't know, the syntax doesn't look very intuitive, but it's probably the best you can get.

Secondly: what I find the most instructive lesson here is however, that we can see that the old notion of destructor isn't so old-fashioned after all! C# has meanwhile its using statement and Java deserves (and needs) some destructor-like mechanism as well! So much for the (former) "modern languages".

--
* form SUN's rebuttal of delegates - http://java.sun.com/docs/white/delegates.html, where they claim that delegates (i.e. C# equivalent of C++ member function pointers) are bad, because the anonymous classes can do all the same ans are object oriented too! A typical case ob the object-craze of the nineties IMHO

** I will only skim the surface here, as my aim is only the look-and-feel. If you need more information a good place to start is: http://www.javaworld.com/javaworld/jw-06-2008/jw-06-closures.html ("Understanding the closures debate - Does Java need closures? Three proposals compared", by Klaus Kreft and Angelika Langer, JavaWorld.com, 06/17/08)

*** rephrased ;-U from the discussion here - http://infinitescale.blogspot.com/2007/12/bgga-closures-end-of-many-java-careers.html, but seen in that form on other places in the Web

**** Let us digress a little: in C# we'd define the above lambda like that:

  Function<int, void> p = name => Console.WriteLine(name);
or use it directly like that:
  names.FindAll(name => name != "Marek")
.ForEach(name => Console.WriteLine(name));

Note that in C++ the lambdas aren't templates (they are monomorphic, i.e. we must define the argument types) but in C# they are! To achieve the same in C++ you have to use a template lambda library.

I mean the C# language is looking increasingly cool, perhaps I should learn it, as everybody can program Java these days???

Thursday, 27 August 2009

Tony Hoare and the meaning of life (well, almost...)

You know, I was always wondering about programming - is it an art, a craft, or is it an engineering discipline? Some crazy hackers maintain it be an art, more down-to-earth types oscillate between craft and engineering.

My personal feeling was that it couldn't be engineering - I missed the scientific part of it, it was too "soft". For me software engineering appeared rather to be a set of rules of thumb for organizing our mental work (functions, classes, modules...), something from the realm of cognitive science perhaps :-). For example I couldn't take my multithreading program and prove it not to deadlock in a future (i.e not yet written, but planned) installment of this blog...

1. The presentation

And then, some months ago, I came across that presentation* given on QCon 2009 Conference by Sir C.A.R. Hoare (aka Tony Hoare of the Hoare logic, Quicksort, and CSP fame) about relationships between programming and computer science.

Computer Science is about how programs run and how correct programs can be constructed *
By the way, I used to dislike the all-present video presentations, which seem to be replacing the old-fashioned articles as programmer's information source of choice. Well, to put it frankly, I hated them! Instead of beeing able to quickly scoop the essentials and then read the article if it'd interest me, I'm now forced to hear for hours to some uninspiring presentations and often to some really horrible accents to boot, as to discover that in the end only the title of the video was interesting!

But on the other side, with the video presentations I'm no able to hear people like Linus Thorvald** and Tony Hoare in person, and it proved to be very rewarding to me in both cases. Watching Tony Hoare was a great pleasure - he's a wonderfully gentle and good humored old man, I'd say my idol of sorts. And as he's got his first degree in philosophy, so he's bound to have some interesting insights in the question at hand.

His answer is both simple and compelling (I'm rephrasing it here):
Software Engineering is an engineering discipline because it uses Computer Science, and Computer Science is a science because its results are exploited and confirmed by software products!*
Sounds at first rather convincing, doesn't it? But wait, for a philosophy major, isn't he overlooking something?

2. Circulus Vitiosus?

Well, embarassingly, it's looking suspiciously similiar to a circular argument , right? For SW Engineering gets justified by the CS but the CS is justified by SW Engineering? It certainly appeared like this to me at the first glance So let us have a closer look at it:

science is: "the systematic study of the structure and behaviour of the physical world, especially by watching, measuring and doing experiments, and the development of theories to describe the results of these activities "***
Does this apply here? Well, maybe, if for "physical world" we substitute the human-built things like hardware and binaries. But wait, don't we rather work with mental constructs instead (you know, languages, functions, classes)? Well, yes, but they are models, like math is a model in civil engineering. In the end it's all about how the binary runs!

engineering is: "to design and build something using scientific principles"***
This one seems to fit perfectly. So both parts of the argument are corrct, but it is a circular one? Let it translate it form English into the language of logic:
(CS usedIn SWEng => SWEng is Eng) and (CS usedIn SWEng => CS is Sc)
You see it's not really circular, as it's two separate propositions, and they are just rephrasing the two above definitions (check it!). Because science is defined as a special, rigorous kind of examination of the physical world, and engineering uses science when dealing with this world directly! But wait again, it's not said that we are allowed to use only scince in engineering, or ist it?

3. The Engineer an the Scientist

This leads us to another interesting aspect of that presentation, which was the comparison between science and engineering, and how they relate to each other. Somehow explaining the above realtionship (I must paraphrase again):

so it's first:
scientists are interested in pure truths, i.e. programs which doesn't have errors, while an engineer must compromise, i.e. live with programs that have got some errors,

and second:
scientists are interested in certainity, while an engineer lives in incertanity, must take risks and perform risk management,

and thus:
scientists should be women, engineers should be men (Yes, he really made this little joke:)

There are several other comparisions along these lines in the presentation, and furthermore, even a gradation between the two extremes like applied scientist or scientific engineer are introduced. So there is (almost) a continuum of positions between the two extremes of pure CS scientist an a common hacker.

And that fact harbors some kind of consolation, particularly if I'm in a very pedestrian project and must do the most boring things. Just remember, you can always move up the ladder, and use more science, more absolute truths, and thus (as the ancients believed) come in contact with more beauty. An that's maybe the ultimate "consolatio philosophiae“, or do you think this is an exaggeration on my part?

--
* all citations are not original but rephrased by yours truly, so if they are wrong it's my fault! Original source: Tony Hoare, "The Science of Computing and the Engineering of Software", QCon Conference, Jun 11, 2009 , London: http://www.infoq.com/presentations/tony-hoare-computing-engineering

** for example this presentation by Linus was fun: http://www.youtube.com/watch?v=4XpnKHJAok8&feature=player_embedded

*** the definitions are taken from "Cambridge Advanced Learner's Dictionary", as I was looking for simplicity: http://dictionary.cambridge.org/