What is software architecture?
I try to define software architecture, both in the large and in the small.
Eric Normand: What is software architecture?
Hi, my name is Eric Normand. I help people thrive with Functional Programming.
So this is an important question. It's an important term we use it a lot. I want to have my try at defining it.
Someone that I respect, Avdi Grimm tweeted the question, "What is your definition of software architecture?"
He asked it in a way that made it seem like there wasn't one definition.
I don't think there is one widely excepted, consensus, definition of software architecture. He didn't either so it seems like we must have some freedom in how we define it.
I'm not an expert on software architecture, but I have some thoughts on it. I think I have a definition that might shed some light on it that is a useful definition. That's a practical definition, as opposed to a more philosophical definition.
These are my ideas on it and feel free to accept them or not. I'd love to get into a discussion about them. Let's get to it.
What is software architecture?
When we're writing software, there are certain decisions we have to make, that every decision has a cost. A cost to change. We might make a decision like, "We're going to use this particular database." Then three years down the road, we have all this data in it. Now it's very expensive to change database. We have code that's written just for that database. It's expensive.
We have some decisions that we make that are very cheap to change. We have this function. We wrote it three years ago. Now we look at it and we say, "Oh, I need to make it do something different." We just go in and we change the function. Very cheap.
Architecture is all of the stuff that is expensive to change. There's going to be a J curve. If you plot out the expense of changing your mind to changing the decision, you sort them by the most expensive to the least expensive. The most expensive ones, there's going to be some curve where they're super expensive to change.
Most of them are this long tail of really cheap changes. Architecture, you draw the line somewhere in that elbow of that curve, and you say, "Everything on this side is architecture and everything else is design." That's the simple distinction there. It's the cost of change.
Before I go further, I do want to say that I like to pick apart the usages of words. We should really be careful with trying to fit one definition to multiple usages of the same word.
With architecture, we have this problem of having different usages. We get confused because they're the same word, but in different ways that we use them. They should have different definitions.
The two usages that we should distinguish here are saying, "Software architecture, in general. What is software architecture? I'm doing architecture. These are architectural decisions." That's one usage. Another is when we say, "This is an architecture, or we are using this architecture. We're going to use the MVC architecture."
This is two different usages. This corresponds to something in real architecture with buildings, you can say, "What is architecture?" "Oh, it's the use of structure to define spaces." I don't know what the actual definition is, but it's some general thing that's trying to leave the door open for whatever you need to be able to do.
Then there are particular architecture. You could say this is Roman architecture. There are some fixed things in that architecture. They used stone, they used arches, and there are certain technologies that they had, the mortar that they used between the bricks, how they cut the stone, etc. That's Roman architecture.
Then you could have modern architecture which is trying to use really straight lines, and clean looks, and things like that.
There's different architectures, but then there's architecture in general. We have the same thing.
I'm defining right now this high cost of change, software architecture in general. We'll define an architecture afterward. Those two things are separate.
We were talking about this J curve. You draw a line somewhere and you say these choices that we make are expensive to change later. We have to get them right, because we're probably not going to have the resources or the time to change them later.
What you wind up doing is choosing these fixed points. You consider them fixed points. You're like, "We're never going to change it."
It's a double edged sword. We're committed to it, whatever drawbacks it has, we're committed to those. We can also rely on them. We're going to assume that they're there, that they won't change.
This lets you move a little more confidently. These things are here, we can rely on them.
Some examples of those fixed points. Usually what's expensive to change is your database, your programming language. Maybe you are building for the web, that's an architectural consideration.
The platform you're going to run on is it mobile? Is it web? Those kinds of things. I said that there're choices, sometimes it seems like you have no choice. "We have to be on mobile," or, "We have to be on the web."
You could imagine someone making the wrong choice saying, "Well, we have to be on mobile," but that was the wrong choice. It's still a choice even though it might be obvious what you should do.
The other thing to consider is, a lot of these things look like infrastructure, and they often are. Infrastructure choices are often expensive to change. That doesn't mean that infrastructure equals architecture. There's just a coincidence that so often the infrastructural choices are expensive to change later.
In theory, to have something like very software oriented choices, like code that's hard to change later.
An example is MVC. MVC is just a design pattern, it's just some code. It's how you organize the code, and what the roles and responsibilities of different parts of the code are. It's not really infrastructure, but it's expensive to change.
Once you've baked in that assumption that you're using MVC, say in your web app, that's going to be hard to change later.
Another thing is, architecture is all about choosing these fixed points. Like I said this is double edge. They make it harder to change later, but you can rely on them. You're making these choices of fixed points, and they're all trade offs. Each fixed point that you choose has some benefits, and it has some costs.
What's important in this discussion, because the benefits could be like, there's a lot of programmers who know that programming language, so it's easy to hire.
The cost could be something like, the license costs $10 million a year for that database. There could be those kinds of costs. In terms of architecture, what you're looking at as the decisions, the benefits and the cost of those decisions, are about increasing or decreasing options.
If you're making an architectural decision, by being a stake in the ground, it opens up possibilities for things being cheaper to change. Maybe they make other things hard to change.
For example, part of the marketing for Java is that, "It is right ones running everywhere." Everywhere is probably an exaggeration, but it is a highly portable language. It works on a lot of different platforms.
By making the architectural choice, we are going to be on the JVM that allows for it to be easier to move to different platforms. Notice, it's decreasing the cost of another architectural choice.
What would have been an architectural choice with some languages, if you were on, let's say C-Sharp in the late '90s, it would be hard to run that on Linux. Now, it's easy because there's Mono, and stuff.
Back then, it was hard. By saying C-Sharp, you are also committed to Windows, but now you can do C-Sharp and move to Linux, so you can change platforms. That kind of choice opens up other possibilities for cheaper changes later. Java is my example.
What your job as an architect, if you're doing architecture, is to strategically choose these fixpoints to optimize for the requirements that you have in your software.
The requirements are often something like, "It has to run on the Web, because our customers can install software on their desktops, but they have a browser and Internet. We have to deliver this over the Web." You're getting a benefit, which is you can reach the customers, but it has a cost.
Being on the Web is full of known costs, like how this client server model, it's got a synchrony, you have browser incompatibilities, stuff like that. It's also going to limit you, you got to deliver HTML. That's the way the Web works.
Having all these constraints, it decreases the options in some areas, but it gives you access to the customers. You could say it increases the options for what back-end you use, the frameworks, what your server is running on, things like that.
You notice there's this matrix of different options and this landscape that you're choosing places on. Whenever you have a landscape, it's good to think of it as optimization. You're putting stakes in the ground, each stake changes the landscape.
You're looking for a set of these fixpoints that can target a certain requirement or a certain set of requirements. That's very abstract. I hope the Web example makes it clear.
You could say, "We're going to target the JVM because we want to be able to run on a variety of commodity hardware." There's a lot of existing infrastructure, existing software for running JVMs and managing them.
You're on the Web, you're running the server and the JVM, then you also say, "We're going to use React." That's another stake in the ground. That opens up a whole other set of options along with a set of costs and constraints.
Look at it like this complex Web of landscapes that, as you choose different spots, fixpoints, it changes the way that all the other ones interact, really complicated.
Sometimes you hear people choosing particular sets of these fixpoints. I often wonder, "What were the requirements that led you to that?" Often, it seems like people are choosing them for secondary or tertiary reasons.
As an example, I worked at a company that did microservices. I wasn't aware at the time when I started, but as I worked at the company longer and longer, I started to think that the reasons we chose microservice architecture, the ability to deploy the pieces independently, the ability to scale horizontally very easily, the isolation of failures, things like that, those things were not actually requirements for our particular piece of software.
The software we were running did not require those things. It made a whole bunch of stuff harder, like the ability to share code, the ability to iterate quickly on a particular feature, because every feature required modifying the repository for multiple services.
Anyway, I feel this is a useful schema for how to think about architecture because if I look back, I wasn't there when they decided to use microservices.
If you ranked all of the requirements in order, what's the most important requirement? There's going to be some that are unknown, that these could really change and these are nice-to-haves, but they're secondary. If you had just rank-ordered them, then the architectural choices that we could have made would be much clearer and more correct. That's my experience with that.
Now, I want to talk about an architecture. When you talk about a particular architecture, because there are some architectures that we know of, that we see in use. For instance, an event source architecture, something like that or an MVC architecture, or you could look at something like a LAMP stack, as an architecture.
These are all sets of architectural choices that define the large-scale schema of how the app, the software is going to operate. You can't just have any set of architectural choices. There has to be enough there to show how the app will work.
In an MVC architecture, let's say Rails, something like that, that is providing the end-to-end flow of how this application is going to work. You couldn't say, "Java with servlets is an architecture." It's not enough, it doesn't tell you how things work.
Once you start getting into MVC, it starts to take some shape. It's going to be database-backed. The routes are going to point to certain operations that store stuff in the database, or it takes stuff out of the database.
You can start to see where the pieces of the software that you write fit into it. In this sense, I think that it's wrong to call microservices an architecture. In general, you can have a particular architecture that makes the choice to use microservices.
Microservices, itself, in general, without more constraints, without more structure, is not an architecture. Just saying, "We're going to break it up into small services," does not tell you how your app is going to work.
An example of an architecture that uses microservices, but that also tells you how the app is going to work, is something I saw in a Fred George talk where it was all about insurance quotes. One of the requirements was that they wanted it to be like a marketplace for insurance quotes.
Someone types in their information, a user types in their information. They submit the form. Then, they're supposed to receive a bunch of quotes. Like, "Oh, if you go with this company, you'll get on this plan. This will be your premium, and you'll be getting covered in this way, and you'll pay this much every month for this plan, etc."
The idea was you submit the form and you get a whole bunch of quotes. The requirements are we don't know what those algorithms for determining the quotes should be yet. We don't know all of the companies that we'll partner with yet, and we need to show the quotes even if one of them fails.
If we can't calculate the quote in time, we need to show the rest of them that did come through.
There's all these requirements. They broke it up into microservices, but the architecture included the structure of how the app should work. When a user submits the form, that is put into a queue, a stream, that different microservices can subscribe to.
All the microservices can get that message that the users submitted their thing and process it in their way. Each microservice defines a different algorithm. Then, when it shows the code, it would put that onto another queue with an ID to tie it back.
After one second, two seconds, whatever of waiting, the server would then gather all the ones that are already on the queue, all the codes, put them together into a response for the user.
Notice how it gives a much more detailed story about how the flow of the app is going to work. How everything is to be structured. It tells you where to put things. Oh, you have a new algorithm for coding an insurance policy? Make a new microservice, and it has to do this, it has to subscribe here and put answers there.
It's not just microservices that has an architecture. Microservices is more like small, architectural decision, but they use the microservices to great advantage because you could deploy separately, you could add new ones at a later time. New services because of the way the architecture was designed.
That's just about all I have to say about software architecture. I'd love to hear what you have to say, whether you agree, whether you have some reference for a better definition than this.
It's something that I'm working on for my book. Not particularly a definition, but I am dealing with a couple of different architectures, right in the second sense, where the whole flow of the app is defined with these architectural decisions. It's good to know what other people have...how they define architecture.
The two architectures that I'm going to be doing soon are the Onion Architecture and the Reactive Architecture for frontend app.
If you like this episode, you can subscribe at lispcast.com/podcast. You'll find text, audio, and video versions of all of the existing, previous episodes.
Please tell your friends if you liked it because chances are, they will like it, too. It will help me out, help spread the word, get more subscribers, and have a wider reach.
Also, please get in touch with me because I love having discussions. My name is Eric Normand. This has been my thought on Functional Programming. Thank you very much for listening and rock on.