| Home | Blog |
Software architecture is knowledge of how a software system is or will be implemented, used to guide software developers in implementing or modifying a software system.
The rest of this article will examine this definition in detail. Objections my view will be addressed at the end.
A software architecture is knowledge. It's not a thing. This is evident from the fact that the architecture for a system can exist before the system itself exists, which is how it can operate as a guide for implementing the system. (It would be valid to classify architecture as a type of specification, which itself is a form of knowledge).
Since architecture is knowledge, then just as knowledge from one human to another about a given thing varies and conflicts, so can each individual software developer's conception of the architecture vary and conflict. Architectural knowledge can vary in detail, one can have a general understanding of how a system is (or will be) implemented or a specific one. One can understand part of the architecture in detail but be vague on other parts. The knowledge can conflict, people can claim opposite things about a system's architecture. The system can actually manifest what are deemed to be mixed conceptions by one person, while another might think that the elements are perfectly consistent.
One's view on the nature of knowledge ("epistemology") as such leads to a position on how these variances and conflicts ought to be resolved, which in turn leads to different views on the role of software architecture in software development. (A future article will address three main views and their consequences in software development).
A software architecture is knowledge of how a system is or will be implemented. It is not merely a list of features a system exhibits or a list of the things that cause this behavior; it is an explanation of how the behavior (the features of the system) is caused in terms of the things that cause it (the elements of the program). It is the conceptual link between what is observed about the system and the set of primitive parts which cause the behavior that is observed.
We know this conceptual link is needed by observing the effects of its abscence. Any software developer who's tried to understand the source code of a system he's never worked with before has experienced what it's like to see an implementation without having an architectural understanding. You don't know why the system as a whole works or how to do anything to properly change it. If you want to change a trivial feature, perhaps you can get away with searching for a string that appears in the application in the source and changing it, but what will be the side effects? You have no idea. Adding a new feature or significantly modifying existing ones is typically a non-starter until you gain a deeper understanding - an architectural understanding - of the system.
Clearly, for other systems merely understanding behavior isn't enough. You can understand how to tell time, but that doesn't mean you can fix a clock. You need to understand how the internal machinery of the clock is arranged to achieve timekeeping before you are reliably able to fix it (obviously if you open it and find a broken spring, you can replace the spring - but assume that there are other parts with settings and tolerances that must be configured properly). And knowing how clock parts work in general is of no use either - you can crack open the case and stare at the gears all you want, even knowing that when one turns it makes another turn does not give you the understanding of how they all work together to keep time. We need more; we need that conceptual link between the parts and their behavior.
Where do we find this link, this architectural understanding? After all, given its critical importance, we ought to have a precise understanding of its source.
Note that if we have only a basic understanding of how the physical parts of the clock work, by examining their arrangements we can eventually gain the knowledge of how the clock works. Likewise in software, if you understand what the individual lines of source code do, you can learn the architecture from the implementation. This is the key to understanding what architecture really is. For any software system, if you know the basic tools used to build it (such as the language it's implemented in), then with enough examination you can come to understand its architecture. It helps immensely to know how the system behaves externally, but even that is not required. You do not even need the source code, given enough time you can gain this insight from examining the machine code.
If this knowledge can arise purely out of the implementation, then that very specifically tells us that the knowledge is of the implementation. This may not be a surprise to some, but to those who have mainly worked in the realm of diagrams, it might.
Does this mean that the only way to ground an architecture in reality is to write the code first and then stand back and observe it after the fact? No. And I'd add: Of course not! Just because knowledge can be gained by looking at the implementation, does not mean that one cannot in essence see the implementation ahead of time. We don't need to actually build clocks in order to design them. We do of course need a basic understanding of the materials we're going to use. But the only limit on what we can do in our heads is our own thinking skills. Indeed, the measure of skill of an engineer might be measured in terms of what he can accomplish before committing to implementation. A good architect can essentially see thousands of lines in a few minutes of thought; clearly, it can be much more efficient to experiment with ideas in the mind before committing something to code. (For historical perspective, compare the engineering methods and results of Nikola Tesla vs. Thomas Edison).
Does that mean that the best approach is to always work in your head? Again: Of course not! Another crucial value of a good architect is his ability to recognize areas where he is not at present capable of discerning the implementation using a high-level approach, areas where he must experiment and discover by writing code. The best engineers don't go to absurd extremes; they use their own individual engineering judgment to determine the best course of action given the circumstances.
There is a sense in which an architecture is implementation independent. To use an analogy from science: are scientific theories independent of the physical objects that manifest them? Yes and no. Yes, because to understand the laws governing a pendulum, you can build any pendulum; it doesn't have to be a particular one with particular measurements. But no, because you must actually build a pendulum in order to run any experiment. The laws are about real things and must be learned from real things. Architecture is implementation-independent in the same sense: it's independent in the sense that many different implementations might yield the same architectural understanding; it's dependent in that unless the architecture can be reduced to at least one implementation, it's meaningless.
Architecture's fundamental purpose is to support software engineering's purpose: to efficiently build software that meets users' needs. Its role as a kind of knowledge is to guide software engineers in pursuit of this fundamental purpose.
These general statements are true, but not enough to determine how to develop an architecture in any particular case. Any real architecture is particular: it is for a particular software system written for particular customers and serves as a guide for particular software developers. The particular needs of each person as an individual comes into play when deciding various things about how to form an architecture; rigid rules are no substitute for good engineers and their case-by-case judgment.
This concrete nature of architectural needs leads to a potentially wide variety of perfectly valid architectural approaches. It can be correct to arrive at a mostly complete architecture without writing a line of code. It can also be correct to start with a vague idea, then write code selected in order to precisely isolate the architecture (but it would never be proper to ignore the architecture, and just write code until the application is complete). It can be valid to document everything. It can also be valid to document nothing. The needs of the project and individuals working on it dictate which is right.
An architecture is essentialized information about the implementation. This follows from its purpose as a guide: it is not intended to substitute for the implementation; it's not supposed to list every possible detail. That would actually undercut its purpose as a guide. The most valuable architectures identify in the briefest possible terms what the implementation is, allowing programmers to confidently, efficiently move between different parts of the source, adding features and fixing bugs.
Some of what I've said about software architecture contradicts conventional notions. In this section I'll deal with noteworthy objections. (If you have ideas for other objections that should be addressed, please contact me via email.)
One might object to my characterization of architecture as reaching all the way down to implementation. Conventionally architecture is about the "high level", and design is the level right above implementation.
I think a somewhat similar objection would be as follows: A parent is one who begets a child, therefore a parent is not a child. This is of course absurd. Here parent/child define relationships between things; one can be both a parent and a child. Architecture and design are relative terms too, when used together 'architecture' refers to a more abstract design activity relative to 'design' which refers to a more concrete activity.
There is no problem with having the different terms; it's useful on a project to refer to both a relatively abstract scale (architecture) and a relatively concrete scale (design). The problem comes in when it's thought that the two refer to fundamentally different things. They are not; they are both in fact just a kind of design. A very complex system has an architecture with modules within it that have their own architecture. Relative to the big system, the modules are "just" designed; but on their own terms they have an architecture. This architecture may be subordinate to the overall scheme set by the broader architecture but it's still an architecture.
This arbitrary line between architecture and design can be harmful. When you think about how to build something, your mind should range over various scales of the problem. The only line that should stop what you think about is defined by what is and what is not important, not by what someone has classified as "high level architecture" vs. "low level design". Systems designed with the dichotomy end up being clunky, as the recurring themes across modules go unaccounted for, and pointless variation is inadvertently introduced into the system. (Sometimes limited time demands an approach that leads to this effect, but it's not a desirable state and should over time be rectified).
Of what use is a clear understanding of software architecture? Explicitly knowing what it is doesn't make one good at it, not explicitly knowing what it is doesn't make one bad at it either.
By knowing that software architecture is a kind of knowledge, we can capitalize on what we know about knowledge in general. We know that there are better and worse ways of seeking knowledge; therefore there are better and worse ways of forming an architecture, and we can be on the lookout for these, avoiding the bad and more consistently applying the good. For instance, we know that a scientific theory isn't validated until it's shown to correspond to evidence; likewise a software architecture isn't validated unless it leads to an efficient implementation - high-level block diagrams alone don't cut it any more than an untested scientific theory.
Since people disagree on knowledge in general, we can expect them to disagree on software architecture, and can come up with ways to help mitigate this inevitability.
Since we know that architecture's purpose is specific to each project and the individuals working on it, we can dismiss any dogmatic rules or processes, and instead seek to understand and adapt what we do to each project's unique characteristics, thereby better serving it.
In other words, to hone the efficacy of your actions, hone your understanding of them. A better understanding of the concept of software architecture is a crucial tool in our quest to become better engineers.
Copyright(c) 2004 Shayne Wissler. All Rights Reserved.