Saturday, August 22, 2009

Difference Between Abstraction & Aggregation

It is easy to confuse abstraction and aggregation. Briefly, I will shed some light on the difference between the two in this article because they are core concepts that must be grasped by any serious architect.

In one of my previous articles I highlighted that the art of abstraction is the bread-and-butter for an architect. I also mentioned that the application of abstraction is behind most, if not all the progress that humanity has made and the enabler of any progress that the humanity will make.

As a recap, abstraction is about generalizing entities, especially complex ones and the ones involving many processes or parts, into one single entity. It is very important to note that this entity must have laser-focused, single responsibility or else this is not abstraction. This generalization accomplishes two major benefits and enablers of human progress. They are paramount for innovation:

1- Simplification. When things are made simpler, we can do more and create more complex innovations. I attributed this mainly to the limitation of how many entities can the human brains grasp at the same time. We must condense in order to progress.

2- Reuse. When something is generalized, it can apply to many more situations and that in turn, will boost progress.

As examples, chances are, I can bet you that anything you think about is an abstraction. A programming function is an abstraction. A class type is an abstraction. A component is an abstraction. Pure Fabrication in GRASP (the activity of creating a new class that doesn't map to a real-life object) is an abstraction activity. The SRP (Single Responsibility Principle) is about abstraction. A SOA service is an abstraction. A framework is an abstraction. An operating system is an abstraction. A car is an abstraction. A post office is an abstraction etc... I hope you catch the drift.

The main thing to note about these abstraction is that they all perform a single responsibility that they accomplish. They are not simply a group of items.

Aggregation on the other hand is one type of abstraction. A subclass of abstraction in that it shares the benefits or purpose of abstraction but with a specific way.

Aggregation is a method of grouping the individual entities under one access point. It doesn't involve responsibility of performing the actual action. Like a catalyst or a middle man. So one major characteristic of this single access point is that it doesn't do any of the functions of the individual parts it is aggregating. Otherwise, it is not aggregation, it is abstraction. Its pure function is to group. That is its meta responsibility. Not to get involved in any of the details (please don't confuse that with delegation).

Examples of aggregation would be a the Facade pattern, a service layer, and a Message Bus. In business, one can see Unions aggregating employees, iTunes as an aggregator of music (iTunes simply groups all the individual artists but is not in music production itself), Google is an aggregator (when you search for electronics, Google doesn't do electronics but they group them for you). Aggregation seems to be the big opportunity in business ventures these days. The name of the game.

With this definition, one can see that aggregation shares the same benefits of abstraction, i.e., simplification and reuse but not its broadness. Aggregation has an already pre-defined single responsibility and doesn't get involved in the function of that which is aggregating, while abstraction is generic, a supertype if you will that most of the time is the function and carries the responsibility itself.

Friday, August 14, 2009

Standarizing Architectural Core Quality Attributes

To differentiate a "good" architecture from a "not so good" one there are a few common quality attributes across the board, regardless of the specific business application. Once we have a common standard, it will be easy to have a basic rating of any software architecture.

When we analyze the quality attributes such a performance, availability, scalability, testability, supportability, usability etc... we notice that we can classify any of them in two broad groups. The dividing line between those two groups is runtime. To simplify, there are pre-runtime quality attributes and post-runtime quality attributes. We can call the pre-runtime ones design-time qualities and the post-runtime simply run-time qualities. For example, scalability is a run-time quality attribute but reusability is a design-time quality attribute. Here are the two groups:

Architectural Run-Time Quality Attributes

1. Availability
2. Interoperability
3. Monitorability
4. Performance
5. Reliability
6. Scalability
7. Security

Architectural Design-Time Quality Attributes

1. Conceptual Integrity
2. Configurability
3. Extensibility
4. Reusability
5. Usability
6. Supportability a.k.a. Readability and Fixability
7. Testability

Upon closer examination we can observe that the run-time qualities vary more often depending on the business application whereas the design-time qualities are standard across the board. For example, in the run-time qualities group, not every system needs to be scalable or highly secure. It depends on the business application. Also, run-time qualities can compete with each other such as performance and security.

On the other hand, all design-time qualities for nearly all systems regardless of their business application can be optimized without negative implications. For example, it is highly beneficial for any system to have excellent usability, conceptual integrity, configurability, extensibility, supportability... the more the merrier. Also, we notice that none of the attributes in the design-time group compete with each other. On the contrary, they support each other.

In conclusion, software architects in general should strive to optimize design-time quality attributes regardless of the business application. Optimizing design-time quality attributes must be a best-practice for software architecture. Design-time quality attributes can be called the architectural "core" attributes.

Thursday, August 6, 2009

The TAO of Software Development: Implement Horizontally & Deliver Vertically

Many development teams struggle with using a consistent approach in delivering quality software. By delivery, I mean the iterative build drop to the customer up to the final release.

Should the task assignment to a developer be use case based or component/feature based? Should we focus our build drops around use cases or components? Should we just let it be in a lassais-faire environment where delivery is haphazard and to each his own?

To know the best delivery method we have to go back to the basics. To a user, the internal components of the software are a black box. A software is developed to satisfy certain human goals and actions, not just for the bits of it.

So a characteristic of the correct method to follow is to be centered around the elementary business process that the user is trying to accomplish. Components do not exist in vacuum.

Vertical Delivery
A user goal or use case is a vertical execution path that spans multiple components. Therefore, to be more client-centric, our deliverable must be organized, tested and delivered to execute use cases. The benefits of this vertical delivery approach include:

1- Early delivery of functional and observable code to the client
2- Early delivery of value for the customer's investment. The "get-hit-by-a-bus" factor is always their concern
3- Effective testability where it is in line with user goals
4- Early discovery of integration issues, since we're always integrating
5- Forcing the creation of a base-line architecture early
6- Forcing the early discovery and resolution of architecturally significant issues

As you can see, the vertical or use case based delivery approach enhances software quality dramatically, mitigates risks and increases the sponsor's return on investment.

Horizontal Implementation
When it comes to assigning development tasks to team members, we should also apply the same reality criteria we used above to arrive at the answer. To start with, software is an ocean of specializations where each one hosts a deep well of knowledge and issues.

Except for small, experimental and throw-away code (.com era comes to mind) projects, it is counter-productive and detriment to quality software to have a team of "do-it-all" developers. Those "do-it-all" developers should be on the way up their career ladders to become Development Leads and Architects.

It is impossible to be an expert at everything. A developer cannot be highly knowledgeable in the intricacies of development technologies such as WCF, Multi-Threading, BizTalk, GUI design, security, compression, web etc... all at the same time.

Plus, the professional maturity level of developers differ. You have the programmer who is a routine coder, then you have the component coder then the application coder etc...

A development dream team is the one that is made up of specialists. A database specialist, a performance specialist, a work flow specialist, a communication specialist, a security specialist etc...

Based on the above reality, the best implementation method that aligns with it is horizontal, not vertical implementation of software. The architect usually determines the needed components and assigns the specialist developer that task (maybe with the help of the development lead). In long standing teams, it is critical to the productivity of a team to have that same developer own that component.

Typically, at the beginning of the software project, the architect builds a matrix of use cases (vertical) vs components (horizontal) needed and adjust in every iteration.