Hi everyone! In this handbook you're going to learn about the vast, intricate field that is Software Architecture. This is a field that I found both confusing and intimidating when I was first starting my journey into coding. So I'll try and spare yo...
The Software Architecture Handbook English Español 中文(简体字) Italiano Português Українська 日本語 한국어 Menu Forum Curriculum Night Mode Donate July 26, 2022 / #api The Software Architecture Handbook German Cocca Hi everyone! In this handbook you're going to learn about the vast, intricate field that is Software Architecture. This is a field that I found both confusing and intimidating when I was first starting my journey into coding. So I'll try and spare you the confusion. In this handbook I'll try to give you a simple, surface-level, easy-to-understand introduction to Software Architecture. We'll talk about what architecture is within the software world, some of the main concepts you should understand, and some of the today's most widely-used architecture patterns. For each topic I'll give a brief and theoretical introduction. Then I'll share some code examples to give you a clearer idea of how these work. Let's get to it! Table of Contents What is software architecture? Important software architecture concepts to know What's the Client-Server model? What are APIs? What is Modularity? What's your infrastructure like? Monolithic Architecture Microservices Architecture What is back end for front-end (BFF)? How to use load balancers and horizontal scaling Where your infrastructure lives On premise hosting Traditional server providers Hosting on the Cloud Traditional Elastic Serverless Lots of other services Different folder structures to know All in one place folder structure Layers folder structure MVC folder structure Conclusion What is software architecture? According to this source: The software architecture of a system represents the design decisions related to overall system structure and behavior. That's quite generic, right? Absolutely. And that's exactly what used to confuse me so much when researching about software architecture. It's a topic that encompasses a lot and the term is used to talk about many different things. The simplest way I can put it is, software architecture refers to how you organize stuff in the process of creating software. And "stuff" here can refer to: Implementation details (that is, the folder structure of your repo) Implementation design decisions (Do you use server side or client side rendering? Relational or non-relational databases?) The technologies you choose (Do you use REST or GraphQl for your API? Python with Django or Node with Express for your back end?) System design decisions (like is your system a monolith or is it divided into microservices?) Infrastructure decisions (Do you host your software on premise or on a cloud provider?) That's a lot of different choices and possibilities. And what complicates this a tiny bit more, is that within these 5 divisions, different patterns can be combined. Meaning, I can have a monolith API that uses REST or GraphQL, a microservices-based app hosted on-premise or on the cloud, and so on. To better explain this mess, first we're going to explain some basic generic concepts. And then we're going to go through some of these divisions, explaining the most common architecture patterns or choices used nowadays to build apps. Important Software Architecture Concepts to Know What's the Client-server Model? Client-server is a model that structures the tasks or workloads of an application between a resource or service provider (server) and a service or resource requester (client). Put simply, the client is the application that requests some kind of information or performs actions, and the server is the program that sends information or performs actions according to what the client does. Clients are normally represented by front-end applications that run either on the web or mobile apps (although other platforms exist too and back-end applications can act as clients as well). Servers are usually back-end applications. To illustrate this with an example, imagine you're entering your favorite social network. When you enter the URL on your browser and hit enter, your browser is acting as the client app and sending a request to the social network server, which responds by sending you the content of the website. Most applications nowadays use a client-server model. The most important concept to remember about it is that clients request resources or services that the server performs. Another important concept to know is that clients and servers are part of the same system, but each is an application/program on its own. Meaning they can be developed, hosted, and executed separately. If you're not familiar with the difference between front and back ends, here's a cool article that explains it. And here's another article that expands upon the concept of client-server. What are APIs? We just mentioned that clients and servers are entities that communicate with each other to request things and respond to things. The way in which these two parts usually communicate is through an API (application programming interface). An API is nothing more than a set of defined rules that establishes how an application can communicate with another. It's like a contract between the two parts that says "If you send A, I'll always respond B. If you send C, I'll always respond D..." and so on. Having this set of rules, the client knows exactly what it has to require in order to complete a certain task, and the server knows exactly what the client will require when a certain action has to be performed. There're different ways in which an API can be implemented. The most commonly used are REST, SOAP and GraphQl. Regarding how APIs communicate, most often the HTTP protocol is used and the content is exchanged in JSON or XML format. But other protocols and content formats are perfectly possible. If you'd like to expand upon this topic, here's a nice article for you to read. What is Modularity? When we talk about "modularity" in software architecture, we refer to the practice of dividing big things into smaller pieces. This practice of breaking things down is performed to simplify big applications or codebases. Modularity has the following advantages: It's good for dividing concerns and features, which helps with the visualization, understanding, and organization of a project. The project tends to be easier to maintain and less prone to errors and bugs when it's clearly organized and subdivided. If your project is subdivided into many different pieces, each can be worked on and modified separately and independently, which is often very useful. I know this sounds a bit generic, but modularity or the practice of subdividing things is a very big part of what software architecture is all about. So just keep this concept in the back of your mind – it'll become more clear and apparent as we go through some examples. ;) If you'd like a bit more info about this topic, I recently wrote an article about the use of modules in JS that you might find useful. What's Your Infrastructure Like? Ok, let's get to the good stuff now. We'll start talking about the many different ways in which you can organize a software application, starting with how can you organize the infrastructure behind your project. To make all this less abstract, we'll use an hypothetical app we'll call Notflix.🤔🤫🥸 Side comment: keep in mind this example might not be the most realistic one and that I'll be assuming/forcing situations in order to present certain concepts. The idea here is to help you understand core architecture concepts through an example, not to perform a real world analysis. Monolithic Architecture So Notflix will be a typical video streaming application, in which the user will be able to watch movies, series, documentaries and so on. The user will be able to use the app in web browsers, in a mobile app, and on a TV app, too. The main services included in our app will be authentication (so people can create accounts, login, and so on), payments (so people can subscribe and access the content... cause you didn't think this was all for free, right? 😑) and streaming of course (so people can actually watch what they're paying for). A quick sketch of our architecture might look like this: A classic monolithic architecture At the left we have our three different front-end apps that will act as clients in this system. They might be developed with React and React-native, for example. We have a single server that will receive requests from all three client apps, communicate with the database when necessary, and respond to each front-end accordingly. The back-end could be developed with Node and Express, let's say. This kind of architecture is called a monolith because there's a single server application that is responsible for all the features of the system. In our case, if a user wants to authenticate, pay us, or watch one of our movies, all the requests are going to be sent to the same server application. The main benefit of a monolithic design is its simplicity. The functioning of it and the set up required is simple and easy to follow, and this is why most applications start out in this way. Microservices Architecture So turns out Notflix is totally rocking it. We just released the latest season of "Stranger thugs", which is an awesome science fiction series about teenage rappers, and our movie "Agent 404" (about a secret agent that infiltrates in a company simulating being a senior programmer but actually doesn't know a thing about code) is breaking all records... We're getting tens of thousands of new users every month from all over the world, which is great for our business but not so much for our monolithic app. Lately we've been experiencing delays in server response times, and even though we've vertically scaled the server (put more RAM and GPU into it) the poor thing just doesn't seem to be able to bear the load it's taking. Moreover, we've kept developing new features into our system (such as a recommendation tool that reads the user's preferences and recommends movies that suit the user profile) and our codebase is starting to look huge and very complex to work with. Analyzing this problem in depth, we've found the feature that takes the most resources is streaming, while other services such as authentication and payments don't represent a very big load. To solve this problem, we'll implement a microservices architecture that will look something like this: Our first microservices implementation So if you're new to all this you might be thinking "what on earth is a microservice", right? Well, we could define it as the concept of dividing server side features into many small servers that are responsible for only one or a few specific features. Following our example, before we only had a single server responsible for all features (a monolithic architecture). After implementing microservices we'll have a server responsible for authentication, another responsible for payments, another for streaming, and the last one for recommendations. The client-side apps will communicate with the authentication server when a user wants to login, with the payments server when the user wants to pay, and with the streaming server when the user wants to watch something. All this communication happens through APIs just like with a regular monolithic server (or through other communication systems like Kafka or RabbitMQ). The only difference is that now we have different servers responsible for different actions instead of a single one that does it all. This sounds a bit more complex, and it is, but microservices offer us the following benefits: You can scale particular services as needed, instead of scaling the whole back end at once. Following our example, when we started to experience performance issues we vertically scaled our whole server – but actually the feature that requested the more resources was only the streaming. Now that we have the streaming feature separated into a single server, we can scale only that one and leave …