Mittwoch, 16. Januar 2008

Should I?

This is the first posting after a long time. Unexpectedly some people noticed that I haven't written much (meaning: nothing) over the last year. So, I think it's a good idea to sumarize my activities and also to discuss some of my approach.

So first: what was it that I did last year. From my point of view (and with the little spare time that is left for me) I have done a lot of things. Almost the whole time through I read  books - though one of them was lightweight entertainment literature all the others were very comprehensive textbooks, all of them dealing with the area of software engineering.

First I finished reading "Generative Programming". I was blown away. The vast collection of sophisticated development technologies and techniques was very mind opening. Following That I took a look at "Software Factories". The downside of this book is that it is a bit Microsoft-specific. The upside are the chapters about formal languages which provide a very good insight in the theory of formal languages. Suddenly I understood what tools like GME, EMF and the like really do. To deepen the knowledge about model driven software development I chose the german book "Modellgetriebene Softwareentwicklung" (there's also an englisch Version of it, but the authors are germans). After that I skimed some chapters of "Code Complete 2" and "Refactoring". The latter of these two books was a bit disappointing because it is just about mechanics of moving and reorganizing code. There is no sense of semantic. This is stuff that can also be learned during "doing". Finally I returned to some more elaborate literature in the form of "Domain Driven Design" which is what I am currently reading. This book provides a comprehensive methodology and a set of very useful patterns for modeling the domain logic of an application. The good thing about it is, that the scope the modelling techniques can be applied to is steadily becoming bigger - from the smallest entities to large scale software development. Very enlightening.

With this mind bending amount of theory I thought I could also do something useful. This is why I started to re-implement an old tool that I developed at the university. It's called the LC2 which means roughly "Learning Computer 2". The purpose of the tool is to teach the  concepts of a von-Neumann-Architecture. The interesting thing is, that students can implement tiny assembler programs (in the assembler language for the LC2) whose execution is then shown visually. The concept of this application can be compared with the MIXX computer that is know from the "The Art of Computer Programming" books by Donald E. Knuth.

Now what is the fascinating thing about "re-coding" an old application? That answer is easy to  be seen: The application contains a lot of interesting areas like building a parser for the assembler language. It deals with concepts of simulation and animation to visualize the flow of program execution. Also, my decision to choose a 3-dimensional visualization scheme fosters the familarity with concepts from that domain. Finally making the LC2 a valuable tool (for instance for using it in environments like a computer cabinet) promotes the usage of concepts from the domain of distributed applications. So, here we have an all-in-one package and implementing all of them using modern technologies and approaches - this is fascinating.

For instance implementing a parser with a tool other than lex and yacc forces to learn tools like boost::spirit and boost::lambda. boost::spirit allows to implement a parser entirely in a syntax that is very similar to an EBNF (A DSL for describing the grammer of a certain class of languages) directly in C++ (so this is a DSEL). Boost::lambda enables the programmer to implement the semantic actions (though this can also be done using phoenix, which is a part of spirit). Thereby lambda expressions let the programmer aggressively avoid using identifiers which is very suitable to this kind of task. This way values can be extracted from recognized patterns in the input text (in my case the LC2 program) and written into internal data storage facilities. It was plain fun to use these two modern techniques but it was only the beginning. Having read "DDD" encouraged me to model the domain logic of the LC2, that is the most imprtant functionality of the LC2 application. This doesn't include visualization, communication, presentation to the user or any other peripheral functionalities. My next goal is to create a running prototype which I can then bed into a whatever kinded application.

Now, the design process of this core functionality has a number of characteristics. First, due to the fact that one of the sources of knowledge is the code of version one its a challenge not to reuse the old design. In parts this is easy because the it "featured"obvious defects like incorrect or non-existing separation of concerns (e.g. simulation and visualization). These are the parts that were easily to be avoided. On the other hand the first design was very dedicated to the usage of design patterns. A developer might reason that this is good because of all the advantages that design patterns do have - understandability, common language, known intention and so on. The problem with this argumentation is that a design pattern is very hard to recognize after its application in a domain specific context. The elements of the pattern will very likely have domain specifiy meanings which cover the roles of these elements in the design pattern. Seen from the other side, if the domain specific meanings were replaced with the roles in the  design pattern then the software will become less understandable. Roles in design patterns are general that no domain knowledge is communicated when the code is read. This is even worse. The core problem here is that there exists only a limited number of design patterns that can be used adequately to transport domain knowledge (This means that their application doesn't obscure the domain model too much). One of the candidates is for instance the Strategy.

So the question is: Should I stick to this aggressive application of design patterns again? And my answer is NO. In parts I have already given the reason. Another important reason is that a developer only thinking in "predefined structures" constrains the solution space too much. Of course it's important to recognize when a pattern should be applied, but this should not be the primary goal. This kind of design process frees the developer from thinking about the real problem.

Having understood the importance of meaning for a sound software design I am glad to be able to attend the OOP conference this year. There I will have the chance to see Mr. Eric Evans speaking about "Strategic design" and to take part in a tutorial covering how DSLs can be created using a tool called GEMS. With these new information I should be able to cultivate my domain modelling skills in the future.