Monday, May 28, 2012

The power of Software Design Patterns

The first day of GeeCON 2012 conference featured a presentation held by dr Ivar Jacobson. His speech called "Liberating the Essence from the Burden of the Whole: A Renaissance in Lean Thinking" made a huge impression on the audience, as it summarized in under an hour his enormous live-long experience in IT industry. It has been a great lesson to anybody who was lucky to attend it.

There was one point, however, I couldn't agree with. Dr Jacobson stated that despite years of its existance software design still lacks universal, solid foundations. Working as a coding architect I have seen a lot of really bad designed and ugly code, including my own. What's more, the abundance of different programming languages and coding styles seems to make things even worse.

There is no single solution that addresses all possible software design problems, but there are some that help solving a great number of those issues. Those universal solutions are called Software Design Patterns. The power of design patterns comes from their pragmatic nature - they are not another product of a software company, university or technical committee, but they are a collection of best practices used by the most skilled programmers to solve the most common programming challenges. The greatest value of software design patterns is that they are universal. It's a common mistake, made even by experienced programmers, to think that design patterns are related only to object oriented programming. They can be applied to any programming language and paradigm. Let me show you how it works.

One of the simplest and yet most powerful design patterns is the state pattern. It allows to easily implement even a very complicated state machine. In this pattern, each state is a separate entity (can be an object), and it is the current state which decides which state comes as the next step of the program. The main loop just holds a reference to the current state and requests it to take certain actions.

State pattern can be used for example to implement a simple ping-pong machine. In this scenario there are two states: ping and pong. Both implement only two functionalities - displaying "ping" or "pong" on the terminal and moving to the next step: in case of ping the next step is pong, and vice versa.

Below is a C++ implementation of a ping-pong state machine. Ping and pong are simple objects that implement two functions: show() and next(). The main program starts with the ping object and than starts to call both methods in a loop. The most crucial element is that the algorithm uses only one reference pointing to the current state. When a transition to the next step takes place, the reference to the previous state is replaced by the new one. This way the main program doesn't need to care about the logic of the state machine, the states take care about it themselves:
#include <iostream>

class State {
public:
    virtual void show() = 0;
    virtual State *next() = 0;
};

class StatePing: public State {
public:
    void show();
    State *next();
};

class StatePong: public State {
public:
    void show();
    State *next();
};

void StatePing::show() {
    std::cout << "ping" << std::endl;
}

void StatePong::show() {
    std::cout << "pong" << std::endl;
}

State *StatePing::next() {
    return new StatePong();
}

State *StatePong::next() {
    return new StatePing();
}

int main(int argc, char *argv[]) {
    State *st = new StatePing();
    for (int i = 0; i < 10; i++) {
        st->show();
        st = st->next();
    }
    return 0;
}
Now you may wonder how can you make use of the state pattern using a functional programming language like, let's say, Erlang? Well, as I sad before, design patterns are universal, so you can use actors instead of objects. Here is Erlang implementation of the state pattern:
-module(states).
-export([state/1, ping/0, pong/0, start/0]).

state(Pid) ->
    receive
        show ->
            Pid ! show,
            state(Pid);
        next ->
            Pid ! {next, self()},
            state(Pid);
        {new, From} ->
            state(From)
    end.

ping() ->
    receive
        show ->
            io:format("ping~n"),
            ping();
        {next, From} ->
            Pid = spawn(states, pong, []),
            From ! {new, Pid}
    end.

pong() ->
    receive
        show ->
            io:format("pong~n"),
            pong();
        {next, From} ->
            Pid = spawn(states, ping, []),
            From ! {new, Pid}
    end.

start() ->
    S1 = spawn(states, ping, []),
    spawn(states, state, [S1]).
"Ping", "pong" and "state" are actors. "State" actor acts as a current state reference - it holds the pid (process id) of the current actor. When you send message "next" to "state" it passes it to the current actor, which spawns a new actor and sends its pid back to "state". This way "state" always holds a pid of the current state represented by actor.
You can load this code into your erlang shell and use observe how it works:
S = states:start().
S ! show.
S ! next.
S ! show.
How about languages that don't support object oriented programming or actors? Have a look at this Scheme example:
(define ping
  (lambda (arg)
    (cond ((equal? arg "show") (display "ping\n") ping)
          ((equal? arg "next") pong))))

(define pong
  (lambda (arg)
    (cond ((equal? arg "show") (display "pong\n") pong)
          ((equal? arg "next") ping))))

(define state
  (let ((current-state ping))
    (lambda (arg)
      (set! current-state (current-state arg)))))

(define repeat
  (lambda (n)
    (let loop ((i 0))
      (cond ((< i n)
             (state "show")
             (state "next")
             (loop (+ i 1)))))))

(repeat 10)
In this example "ping" and "pong" are first class functions which can be passed as arguments to other expressions. Reference to ping or pong is stored in the "state" function, which acts as a closure. It means that the value of the current-state variable is being retained between subsequent calls of the "state" function.

But what if you are a real hardcore hacker who despises high level programming languages and codes only in assembly? Or maybe there are some cases when you may have to? Well, than I have somehing for you too - here is a short state machine written for 64-bit Linux in Intel x86 assembly using The Netwide Assembler:
global  _start

section .data
    ping_msg:  db  'ping', 0x0A
    ping_len:  equ $-ping_msg
    pong_msg:  db  'pong', 0x0A
    pong_len:  equ $-pong_msg

section .text

_start:
    ; init first state
    mov     rsi, _ping_show
    mov     rdi, _ping_next
    ; repeat 10 times
    mov     rcx, 10
_loop:
    push    rcx
    call    rsi            ; show
    call    rdi            ; next
    pop     rcx
    loop    _loop
    ; finish
    mov     rax, 60         ; sys_exit
    mov     rdi, 0          ; exit code
    syscall

_ping_show:
    mov     rax, 1          ; sys_write
    mov     rdi, 1          ; stdout
    mov     rsi, ping_msg
    mov     rdx, ping_len
    syscall
    mov     rsi, _ping_show
    mov     rdi, _ping_next
    ret

_ping_next:
    mov     rsi, _pong_show
    mov     rdi, _pong_next
    ret

_pong_show:
    mov     rax, 1          ; sys_write
    mov     rdi, 1          ; stdout
    mov     rsi, pong_msg
    mov     rdx, pong_len
    syscall
    mov     rsi, _pong_show
    mov     rdi, _pong_next
    ret

_pong_next:
    mov     rsi, _ping_show
    mov     rdi, _ping_next
    ret
To compile the assembly example in Linux use the following commands:
nasm -f elf64 -o states.o states.asm
ld -o states states.o
In this case index registers rsi and rdi are used to keep references to the current state. The main loop just calls "_show" and "_next" subsequently and the "ping" and "pong" states take responsibility for passing valid pointers to the CPU registers.

As you can see, you can use design patterns to properly implement soultions to some universal software desing problems. You only need to be aware of the strength and possibilities of your current programming language and use them wisely.

Sunday, April 22, 2012

AmigaE for PC

Some old computers are like cult cars - they have souls. Those computers were designed with passion by the greatest visionaries of their times, like Jay Miner or Steve Wozniak. Although Apple is the only brand which has successfully resisted the Wintel domination on the personal computer market (partly by adopting x86 architecture) there are still many devoted fans of other architectures, who not only cherish the memory of their favourite computers by writing new software and organising demoparties, but also by building entirely new machines. Amiga community stands out strongly in this area: you can buy not only hardware like AmigaOne (Sam440 / Sam460) or Natami, but also a new version of AmigaOS called AmigaOS 4. PC users can download AROS, which is an operating system designed to be as compatible as possible with original AmigaOS. I used it for a while on Acer Aspire One Z95 and was very impressed - it was not only blazing fast (booting in less than 8 seconds), but also allowed me to connect to a WiFi network and browse web sites.

The most popular programming languages for Amiga (except assembly and C) were Amos and AmigaE. Amos inspired some PC game programming systems like PlayBasic, DarkBASIC or sdlBasic, but AmigaE successors were for many years available only for MC680x0 CPUs. Now you can get PortablE, which is an improved recreation of AmigaE, and use it to write AmigaE programs on Windows. The only requirement is that you need MinGW installed (I use easy to install TDM-GCC bundle) and cannot use some multimedia libraries, which have not been ported to x86 architecture. However, all shell examples compile and run smoothly, so if you are an Amiga fan (like me) and want to have some fun, you can go back for a moment to writing software in AmigaE again.

Wednesday, April 4, 2012

Mongoose - small embeddable web server

David Bolton is a software developer and blogger I respect very much not only for his programming skills, but also for his willingness to share his knowledge with others. He runs the best blog dedicated to programming in all falvours of C (ANSI C / C++ / C#) I have seen so far. You can find there a lot of tips, tutorials, quizes and sometimes description of interesting and yet less known software.

Recently David mentioned an interesting project called Mongoose, a small cross-platform webserver written in C. On the contrary to another beforementioned C-based web server G-WAN, which is not embeddable, closed source, and supports only Linux (Windows version can be downloaded, but is not supported), Mongoose is fully embeddable, open source and runs on Linux, Windows, MacOS X and Android. Currently Mongoose provides bindings to Python and C# as well as support for CGI scripts (including PHP), and as addition to this it can be easily embedded into your C/C++ application. Of course, if you want to retain flexibility and run C servlets along with other scripts, you can still use Tiny C Compiler through CGI. Mongoose requires no installation and can be run with one click (on Windows) or command (on Linux), so it can be used for example to easily share some files on the local network via web interface.

By the way, there is another popular project with the same name. It is a Node.js library for MongoDB.

Thursday, March 29, 2012

GeeCON 2012 registration is open!

If you would like to attend one of the biggest Java conferences in Europe and hear some renowned speakers like Adam Bien, Isabel Drost, Bruce Eckel, Ivar Jacobson or Simon Willnauer live, you are welcome to register at http://2012.geecon.org/. It's a great place to share your thoughts and experiences with some most passionate Java experts from all over the world. It would be great to see you on 16th-18th May 2012 in Poznań, which is also one of the host cities of the UEFA 2012 European Football Championship.

Wednesday, November 2, 2011

Gomemcache with multiget support

It's my pleasure to announce that gomemcache already has six contributors that have supplied changes and fixes to the original code base. A recent patch by Arbo von Monkiewitsch adds GetMulti() function that allows fetching values for multiple keys with one function call.
As a side note, one thrid of patches, as well as a few of my commits, are purely compatibility fixes for subsequent Go releases. I think that at the moment frequent changes to the standard libraries and the language core are the main blocker preventing wide adoption of Go by the IT industry.

Friday, September 16, 2011

Human factor

Having recently moved to a netbook, I realized again how important performance is for software development. I realized it even more when my Android phone became almost unusable after another software upgrade. As a kid I was a big fan of a computer demoscene where gifted coders showed to the world how to make the hardware do things unimaginable even by its creators (like a famous Commodore 64 FLI graphic mode). Now when the number of small devices connected to the Internet exceeds the number of computers and laptops wired to the global network, writing efficient software is a must: Facebook develops HipHop for PHP (written in C++), Google releases Native Development Kit for Android and makes Go the first compiled programming language available for the Google App Engine platform.

It is commonly argued that ANSI C is the "fastest programming language" that exists. No it's not. The language itself is neither slow nor fast, it's the implementations that are (compare Ruby and JRuby for example). However, it's true that software written in C can be usually compiled to the most efficient executable code (excluding pure assembly). No wonder that the most efficient pieces of software, like operating system kernels (Linux, BSD, Solaris, Windows, etc) or programming language VMs (Common Lisp, Python, PHP, Ruby, and even Java) are all written almost exclusively in C (not even C++).

Out of curiosity I started to look around for web software written in C and found a wonderful web server called G-Wan. It's very small and its performance looks really amazing as compared to other web servers - some enthusiastic reviews even call it The Future of the Internet and wonder why such a brilliant software is not popular. Well, G-Wan is not popular, because there is a problem. A big problem. And the name of the problem of G-Wan is Pierre Gauthier, its author. If you browse through the G-Wan's website and forum you can learn that he is a man with a really huge ego (he calls himself one of the best engineers available), who loves to criticize other people's work (like Poul-Henning Kamp's, the author of Varnish). But at the same time he does not want to publish his own source code nor make it open source, because he perceives other developers as inferior idiots, who would surely break it or at least bring nothing interesting to the existing code base. Moreover, evil government agents will try to introduce backdoors into his software and you are more secure when Pierre hides his code deep under his bed and tells you that you should trust him. And of course you do, don't you? And if you invest your time and money in G-Wan you don't have to worry at all about future development and maintenance, because even though the source code is closed, Pierre also gives you his word that he will not drop the software, and that he will never get hit by a bus (I'm not exaggerating, just read this post). I will not go deeper into his paranoia of his website being constantly attacked by Microsoft and NSA servers, because you already should have an idea about the way the guy thinks.

Edit: On the contrary to the information provided by its author, some security problems have actually been found in G-Wan. The affected version 2.10.6 is no longer available, and the issue was addressed by Pierre in his usual manner (one of the most funny claims is that nobody ever tried to confirm the bugs, while there is no archive of older G-Wan versions to verify it). Also, any links leading to the report are being actively removed from Wiki pages (see the comments to this post for details).

On the other pole there is a true pearl called Tiny C Compiler created by Fabrice Bellard. It's so insanely fast (it can compile the typical Linux kernel in less than 15 seconds!) that it can be used to write scripts or servlets in ANSI C (guess what is used internally by G-Wan to compile the servlets). With another open source project, libmicrohttpd, it can become a good alternative if you want to build a small, fast web server that can use ANSI C servlets (for example as an embedded router software). Libmicrohttpd is fully HTTP 1.0 and 1.1 compliant, and it offers several threading models, so you can tune your software and choose which one suites you best in your environment. If I was supposed to build a tiny embeddable web server, I would definitely choose open source libmicrohttpd + tcc + some personal coding over G-Wan.

P.S. G-Wan's author deleted forum from his website, also ensuring (with carefully crafted robots.txt file) that none of its contents is archived by search engines. The forum contained many important information for G-Wan users, but user support is obviously less important than invalidating links in this and other unfavourable posts. Of course you are still welcome to believe in "source code insurance", and that the same will never happen to G-Wan.

Friday, September 2, 2011

Another one bites the dust

A few days ago I found an interesting post on Ken Shirriff's blog, entitled Why your favourite language is unpopular. It summarizes a talk by Erik Meijer who provided a simple, yet very accurate, explanation why some programming languages gain popularity, while some other (often better in many aspects) don't. I thought about this formula in context of Reia, a very promising language for Erlang platform I mentioned about back in 2008 in my post Scripting Erlang. The author of Reia has just announced that he drops development of Reia in favour of Elixir. It seems that with the amount of software existing today there is very little space for another programming language, even if it addresses problems hard to solve with mainstream languages. With existing army of programmers at its disposal, the IT industry can deal with most of its problems using existing tools, without the need of inventing another language to rule them all. A good example of such philosophy is Cilk Plus, which originates from Cilk and allows to scale C/C++ code easily on multicore CPUs. With Cilk you can improve your existing software without rewriting it from scratch with a new computer language, which in the long run can create more problems than it actually solves.