If you are a software engineer: DON'T PANIC! This blog is my place to beam thoughts on the universe of Software Architecture right to your screen. On my infinite mission to boldly go where (almost) no one has gone before I will provide in-depth coverage of architectural topics, personal opinions, humor, philosophical discussions, interesting news and technology evaluations. (c) Prof. Dr. Michael Stal
Tuesday, June 27, 2006
Aspects r' us
A valid question in this context always is: should one use AspectJ as a kind of DSL in addition to a programming language such as Java or is it better to apply generative techniques such as MDSD to generate the solution from a DSL? Challenge: the runtime aspects of AspectJ have no counterpart in generative approaches. A possible approach then would be to use integrated DSLs to provide different views in a multi-dimensional approach. For example one DSL for the domain, one for security, one for fault-tolerance. From these descriptions a MDSD generator would then generate Java and AspectJ code. This would make aspects an implementation issue.
No matter how we view it, we always have to cope with multiple dimensions. Unfortunately, as already stated, the number of dimensions is proportional to the complexity of the problem space. Inherent complexity can not be removed (in contrast to accidental complexity). The implication therefore is: either the complexity arises at the OO level or in the architecture or in the DSLs and their combination as well as in the use of these DSLs. Thus, we have to deal with this complexity. Until now no one ever came up with a really complete and consistent solution. Actually, that is exactly the reason why it is so difficult to meet operational and developmental qualities in a software architecture. It is a question of complexity.
From my current viewpoint a combination of domain modeling, AOSD and MDSD seems to promising. But maybe, sometime in the future, someone can come up with the grand unified theory of software engineering.
My conclusion: even if you don't program aspect-oriented and even if you don't use aspects, you will have to deal with them anyway. Thus, tools such as AspectJ are important as thought-provoking mindset.
I am curious about your opinion!
Saturday, June 24, 2006
Variabilities
Development time: The target address could be hard coded into the client code. Compile/Link time: The target address is separated into a different file which is compiled and linked to the component (e.g. a proxy generated using WSDL).
Deployment time: The target address is specified by a configuration file which the container parses. It then passes the target address to the component (or a proxy) using dependency injection upon instantiation of the component.
Maintenance time/Runtime: The proxy which the component used to access the remote object is implemented as a DLL or shared library. This DLL might be exchanged at runtime by the container either using hot deployment at runtime or when the operation of the applications is paused for maintenance.
Patterns such as Decorator, Proxy, Interceptor or Strategy are helpful to deal with these variablities. Programming languages also offer great support for variabilites when they provide concepts such as interfaces, polymorphism, generic types. It is important to mention that each of these different binding times of a variability reveals different implications. For example, runtime binding is very flexible but might lead to performance penalties. In other words, the more loose coupling is introduced between the implementation of a variability and the application, the more flexible the application might be, but also the more resource consumption might be involved.
Another important point in this context consists of the fact that variabilities might be dependent on other variabilities which can be described using feature modelling. For example, if we use remote object RO1 then we also need to access RO2. Thus, the binding time and order need to be determined in advance. But that is a topic for a future posting.
Thursday, June 22, 2006
The Arrival of Language Integrated DSLs
Saturday, June 17, 2006
Lisp again!
There he addresses how developers can learn Lisp. I like this posting because in recent research projects I've made the personal observation that people tend to constantly reinvent the wheel. A good example are developers that grew up with Java or C++ or C#. They are often astonished with new and cool language capabilities such as closures (Ruby), or lambda-expressions (LINQ). Why am I talking about this issue? The good ole languages such as Lisp, Prolog invented several of the features that are so exciting. For example, model-checking in model-baased software development is a good example where Prolog turns out to be a clear winner. And Lisp simply is the singularity where the big bang of dynamic languages originated. Knowing these languages is absolutely valuable. Know the idioms of these languages and you will benefit in your daily developer life. Eric Meijer said recently on a conference: "you should learn a new language each year". That's the right strategy :-)
Complexity and Software Architecture
At university we have learned that the complexity of algorithms is measured by the amount of "processing time" it takes to solve a given problem depending on the number of input values, e.g.:
- O(c) means that to solve a specific problem always needs the same time independent of the input. Example: a constant function that always returns 42.
- O(N) means that the processing time reveals liner increase with the input dimensions.
- O(log N): time for searching an element in a sorted field.
- O(N log N): time to sort an unsorted field of N values.
We know that if we can map a given problem in constant time to let's say a sorting problem, and vice versa, then the problem will also have O(N log N) complexity. However, this kind of complexity is not that significant for software architecture design, is it? At least, we start to assume that there might be differend kinds of complexity.
In the old latin language complexity was defined as the total set of possibilities and capabilities. Thus, we can draw the conclusion that a software architecture is complex if it reveals a large set of properties and capabilities.
An appropriate way to get a gut feeling for software architecture complexity is to ask the following question: What are typical implications when a software architecture IS complex?
Static Structure:
- The architecture consists of a whole ocean of entities with lots of different relationships
- It typically comprises insufficient or confusing abstractions
- There is no clear separation of concerns. For instance, some entities are overloaded with various unrelated responsibilities, a point that is is often tightly related to the previous issue
Dynamics:
- There are lot of possible workflows
- The system contains many states and transitions
As you surely know the old saying is that software architecture and organization are only two sides of the same coin. Complexity of architecture may thus be caused by your organization:
- No clear team responsibilities and role assignments
- Insufficient or missing process
- High level of political issues in daily work
- Documentation-addiction
- Missing doucumentation
- Insufficient amount of time dedicated to architecture design
- No supervision of architecture realization
- Lack of adequate testing
- No sufficient team education upfront
In summary, complexity in software architecture is mainly caused by missing or overused abstractions and inadequate separation of concerns in either static structure or dynamics. Or in other words, the RUP 4+1 view helps us to structure complexity in different (4+1) areas. In addition, inadequate processes, tools, education, and organizational issues inevitably cause software architecture complexity.
Good means to prevent complexity are manifold:
- software patterns
- usage of frameworks and containers
- aspect-oriented programming if done right
- model-based software development if done right
- higher abstraction by introducing domains specific languages and domain modelling
- metrics if applied right
- usage of appropriate methods and tools
- requirements traceability
- ...
All of these means help to obtain appropriate abstractions, and mapping of responsibilities to entities. Note, that humans are normally only capable of processing 8 entities at the same time. Hence, this point should be taken into account on each abstraction layer and for each architectural perspective.
But that's only my 2c.
I am wondering what your opinions are w.r.t. complexity? Any complexity definition that makes sense?
Saturday, June 10, 2006
Michael's Pattern Laws
Here are some laws I found in the last years as a software architect I'd like to share of you. Maybe, you could share your own insights.
- Patterns are no surrogate for human intuition and creativity.
- Overload of patterns in your software architecture implies overload of problems in your system. However, not using patterns where applicable may make your life extremely unpleasant.
- If you just found that cool new pattern, think again before bothering the rest of us! (Remark: I also want to remind you of Brian Foote's famous words: " a pattern is an aggressive disregard of originality").
- Patterns are your best friends if they are treated with friendliness in your architecture design.
- It is easy to become a pattern author but it is surprisingly hard to write a good pattern description.
- If grandma understands it, it is propably a good pattern description.
- Patterns that can be easily formalized are no patterns.
- Patterns and Agility? Patterns are about agility. Without patterns your software architecture tends to become overly complex and thus hard to maintain, change, or evolve.
- The number of pattern books has significantly increased in the last years but that is not necesssarily a sign of good quality.
- Patterns are dead, CORBA is dead. All technologies that turn from hype to pragmatic technologies are declared dead once upon a time. If a technology is considered that way, it is typically safe and valuable to use.
- A pattern is no island. It reveals its true power when connected with other patterns to form complete landscapes.
- You can classify patterns in infinite ways. For example in structural, behavioral or creational patterns such as GoF. Or you may partition the pattern space with respect to granularity, process phases or domain facets. I prefer to have only two classes of patterns, good ones and bad ones.
- Time is money. Applying patterns saves time. Thus, patterns are money! Don't forget to tell that your managers.
- Always add a real life example to your pattern descriptions because some non-software people in your projects won't see the value of patterns otherwise. Take management as an example.
- If you are a good guy, apply patterns. If not, anti-patterns might be a more appropriate choice.
- Patterns are not just collections of UML diagrams. I totally agree with Bertrand Meyer who once said "bubbles don't crash" and "all you need is code". Developers should memorize those sentences.
- Applying the right patterns the right way is like paradise. Applying the wrong patterns or applying the right patterns wrongly, however, is like hell. Thus, make sure you know what you are doing here.
- Sure, you got all pattern books. But that doesn't make you a pattern expert automatically.
- As the pointy-haired boss always ephasizes in Dilbert "work smarter not harder". Applying patterns is generally considered smart.
- Beware of Murphy's Laws when applying patterns.