In my post about Event sourcing and CQRS, I touched on software architecture, but assumed it was already defined. I’d like to dive into that a bit more based on some recent reading.
My definition of software architecture is providing structure that allows productive, effective software development to occur.
Provides structure means having the appropriate technology, practices, culture, and organization in place to allow flourishing. As a software developer I tend to think of the technology (the code) first, but it is certainly not the only thing needed to have effective software architecture. More on that later.
Productive, effective software development means producing software that meets the needs of the business. There are 2 ways that software meets the needs of the business:
- What the software does
- How it does it
Or to use more formal terminology:
- Functional requirements
- Non-functional requirements
The functional requirements are the business behaviors that provide value to the customer. So for example, if we are creating software for a library, we need the ability to check out books, check in books, and keep a library catalog. Each of these has several behaviors behind it, and there are probably other behaviors I am missing.
The non-functional requirements are also known as the “-ilities” that describe things about the software besides its function. For example, testability is how easy the software is to test. Maintainability is how easy the software is to maintain. There are many others:
Besides the above, non-functional requirements might relate to the skill level of developers required to maintain the system, or the structure of the development teams that maintain it. (e.g. the presence of an off-shore development team)
The central claim of software architecture is that you can implement functional requirements in any architecture, but different architectural styles have different non-functional characteristics. What do I mean by that? They provide software structures that emphasize some characteristics at the expense of others. This is a classic engineering trade-off. The job of the software architect is to select an appropriate software structure that matches the non-functional requirements, which should also match the business expectations.
My term “software structure” would overlap with the term architectural pattern, which I first heard about from Mark Richards. Some examples of architectural patterns include:
- Layered architecture
- Microkernel architecture
- Pipes and filters architecture
- Service oriented architecture
- Event driven architecture
- Space-based architecture
Ah yes, microservices, the buzzword of the last few years. I don’t have time to go into microservices in this blog post, but check out Jimmy Bogard’s Microservices FAQ for more info.
I mentioned earlier that there are different aspects of providing structure. In addition to architectural patterns, which affect the code (technology), there are:
- organizational patterns (e.g. are teams organized by business capability or by similar job roles? What is the mapping between products to teams?)
- practices (such as TDD or Extreme programming)
- culture (probably another blog post altogether)
Ideally all four aspects of structure work together to accomplish the desired outcome. (I’m not sure of the origin of this list of 4 items came from, if anybody knows, leave a note in the comments.)