What is software architecture?
The software architecture of a system represents the design decisions related to overall system structure and behavior.?
Software Architecture refers to how a system is organized in the process of creating software covering, but not limited to:
- Design Decisions (Is the system a monolith or is it divided into microservices?)
- Implementation Decisions (Do you use server side or client side rendering? Relational or non-relational databases?)
- Underlying Technology (Do you use REST or GraphQl for your API? Python with Django or Node with Express for your back end?)
- Infrastructure Decisions (Do you host your software on premise or on a cloud provider?)
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).
- 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.
- An API (application programming interface) 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.
- "Modularity" in software architecture refers to the practice of dividing/breaking things down 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.
What's Your Infrastructure Like?
There are many different ways in which you can organize a software application, starting with how can you organize the infrastructure behind your project.
A quick sketch of monolithic architecture might look like this:
- At the left there are three different front-end apps that will act as clients in this system. They might be developed with React and React-native, for example.
- There is 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.?
- 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
- Microservices is an architecture that is more complex to set up and manage for very big projects. Most projects will start out as monoliths and migrate to microservices only when needed for scalability & performance reasons.
- A microservices architecture will look something like this:
Microservices offer the following benefits:
- Microservices could be auto-scaled as needed, instead of scaling the whole back end at once.?
- Features will be more loosely coupled, which means they could be developed and deployed independently.
- The codebase for each server will be much smaller, simpler, easier and quicker for new developers to understand.
What is back-end for front-end (BFF)?
- One problem that comes up when implementing microservices is that the communication with front-end apps gets more complex. Having multiple services means front-end apps would need to keep track of that info to know who to make requests to.
- Normally this problem gets solved by implementing an intermediary layer between the front-end apps and the microservices. This layer will receive all the front-end requests, redirect them to the corresponding microservice, receive the microservice response, and then redirect the response to the corresponding front-end app.
- The benefit of the BFF pattern is that the benefits of the microservices architecture are realized without over complicating the communication with front-end apps.
Load balancers and horizontal scaling
- Vertical scaling means adding more resources (RAM, disk space, GPU, and so on) to a single server/computer. Horizontal scaling on the other hand, means setting up more servers to perform the same task.
- Instead of having a single server responsible for specific service, having multiple servers handling requests from multiple clients enables exponential scaling.
- This distribution of requests is normally performed by a thing called a load balancer. Load balancers act as reverse proxys to servers, intercepting client requests before they get to the server and redirecting that request to the corresponding server.
- Horizontal scaling is also possible with databases as it's possible with servers. One way of implementing this is with a source-replica model, in which one particular source DB will receive all write queries and replicate it's data along one or more replica DBs. Replica DBs will receive and respond to all read queries.
The advantages of DB replication are:
- Better performance: This model improves performance allows more queries to be processed in parallel.
- Reliability and availability: If one of your database servers is destroyed or inaccessible for any reason, data is still preserved in other DBs.
- So after implementing a load balancer, horizontal scaling and DB replication, our architecture might look like this:
Where Your Infrastructure Lives
- On premise means you own the hardware in which your app is running. In the past this used to be the most traditional way of hosting applications. Companies used to have dedicated rooms for servers to be in and teams dedicated to the set up and maintenance of the hardware.
Traditional Server Providers
- A more comfortable option for most companies are traditional server providers. These are companies that have servers of their own and they just rent them. You decide what kind of hardware you'll need for your project and pay a monthly fee for it (or some amount based on other conditions).
- What's great about this option is that you don't need to worry about anything hardware-related anymore. The provider takes care of it, and as a software company you only worry about your main goal, the software.
- Another cool thing is that scaling up or down is easy and risk free. If you need more hardware, you pay for it. And if you don't need it anymore, you just stop paying.
- If you've been around technology for a little while you've probably heard the word "cloud" more than once. At first it sounds as something abstract and kind of magical, but actually what's behind it is nothing more than huge data centers owned by companies like Amazon, Google, and Microsoft.
- At some point these companies found out they had HUGE computing power they weren't using all of the time. And as all this hardware still represents a cost whether you're using it or not, the clever thing to do is to commercialize that computing power to others.
- And that's what cloud computing is. Using different services like AWS (Amazon web services), Google Cloud, or Microsoft Azure, we're able to host our applications in these companies' data centers and take advantage of all that computing power.
- The first way is to use them in a similar way you'd use a traditional server provider. You select the kind of hardware you want and pay exactly for that on a monthly basis.
- The second way is to take advantage of the "elastic" computing offered by most providers. "Elastic" means that the hardware capacity of your application will automatically grow or shrink depending on the usage your app has.
- For example, you could start out with a server that has 8GB of RAM and 500GB of disk space. If your server starts getting more and more request and these capacities are no longer enough to provide good performance, the system can automatically perform vertical or horizontal scaling.
- The awesome thing about this is you can configure all this beforehand and not have to worry about it again. As the servers scale up and down automatically, you pay only for the resources you consume.
- Another way in which you can use cloud computing is with a serverless architecture.
- Following this pattern, you wont have a server that receives all requests and responds to them. Instead you'll have individual functions mapped to an access point (similar to an API endpoint).
- These functions will execute each time they receive a request and perform whatever action you programmed them for (connecting to a database, performing CRUD operations or whatever else a you could do in a regular server).
- What's very nice about serverless architecture is that you forget all about server maintenance and scaling. You just have functions that get executed when you need them, and each function is scaled up and down automatically as needed.
- As a costumer, you pay only for the amount of times the function gets executed and the amount of processing time each execution lasts.
- You can probably see how elastic and serverless services offer a very simple and convenient alternative for setting up software infrastructure.
- And besides server-related services, cloud providers offer tons of other solutions such as relational and non-relational databases, file storage services, caching services, authentication services, machine learning and data processing services, monitoring and performance analysis, and more. With everything hosted in the cloud.
- Through tools like Terraform or AWS Cloud formation we can even set up our infrastructure as code. Meaning we can write a script that sets up a server, database, and whatever else we might need on the cloud just in a matter of minutes.
- This is mind-blowing from an engineering point of view, and really convenient for us as developers. Cloud computing nowadays offers a very complete set of solutions that can easily adapt from tiny small projects to the biggest digital products on earth. This is why more and more software projects nowadays choose to host their infrastructure in the cloud.
- As previously mentioned, the most used and well known cloud providers are AWS, Google Cloud and Azure. Though there are other options too like IBM, DigitalOcean, and Oracle.
- Most of these providers offer the same kind of services, though they might have different names. For example, serverless functions are called "lambdas" on AWS and "cloud functions" on Google cloud.
TOP ARCHITECTURE CHARACTERISTICS
- The ability for the system to perform and operate as the number of users or requests increases. Scalability is achievable with Horizontal or vertical scaling of the machine or simply attaching AutoScalingGroup.
- Traffic Pattern:?Understand the traffic pattern of the system. It’s not cost-efficient to spawn as many machines as possible, even if it is underutilization.
- Diurnal Pattern:?Traffic increases in the morning and decreases in the evening for a particular region. Global / Regional: Regional Heavy usage of the application.
- Thundering Herd: Many users are requesting resources, but only a few machines are available to serve the burst of traffic. These could occur during peak time or in densely populated areas.
- Elasticity: Ability to quickly spawn a few machines to handle the burst of traffic and gracefully shrink when the demand is reducing.
- Latency: Ability to serve the request as quickly as possible. This also includes optimising the algorithms and replicating the system near users to reduce the round trip of a request. An average google search takes 400 ms.
- It is measured as a percentage of uptime and defines the proportion of time that a system is functional and working. Availability is affected by system errors, infrastructure problems, malicious attacks and system load.
- Deployment Stamps: Deploy multiple independent copies of application components, including data stores
- Geodes: Deploy backend services into a set of geographical nodes, each of which can service any client request in any region.
- Extensibility measures the ability to extend a system and the effort required to implement the extension. The extension can be through adding new functionality or modifying existing functionality. The principle provides for enhancements without impairing current system functions.
- Modular / Reusability: Reusability, together with extensibility, allows technology to be transferred to another project with less development and maintenance time, as well as enhanced reliability and consistency.
- Pluggability: Ability to easily plug other components like in the case of microkernel architecture.
- Consistency guarantees that every read returns the most recent write. This means that after the execution of every operation, the data is consistent across all the nodes, and thus all clients see the same data at the same time, no matter which node they connect to. Consistency improves the data freshness.
- A system can gracefully handle and recover from accidental and malicious failures. Detecting failures and recovering quickly and efficiently is necessary to maintain resiliency.
- Disaster Recovery: Disaster recovery (DR) consists of best practices designed to prevent or minimize data loss and business disruption resulting from catastrophic events — everything from equipment failures and localised power outages to cyberattacks, civil emergencies, criminal or military attacks, and natural disasters.
- Bulkhead: Isolate elements of an application into pools so that if one fails, the others will continue to function.
- Circuit Breaker: Handle faults that might take a variable amount of time to fix when connecting to a remote service or resource.
- Leader Election: Coordinate the actions performed by a collection of collaborating task instances in a distributed application by electing one instance as the leader that assumes responsibility for managing the other instances.
- Usability can be described as the capacity of a system to provide a condition for its users to perform the tasks safely, effectively, and efficiently while enjoying the experience. It is the degree to which specified consumers can use software to achieve quantified objectives with effectiveness, efficiency and satisfaction in a quantified context of use.
- Accessibility: Make the software available to people with the broadest range of characteristics and capabilities. This includes users with deaf, blind, colourblindness, etc.
- Learnability: How easy users can learn how to use the software?
- API Contract: For Internal teams, understanding the API Contracts can help easily pluggable into any system.
- Observability is the ability to collect data about program execution, internal states of modules, and communication between components. To improve observability, use various logging and tracing techniques and tools.
- Logging: There are different types of logs generated within each request: event logs, transaction logs, message logs and server logs.
- Alerts & Monitoring: Prepare monitoring dashboards, create SLI (Service Level Indicators) and set up critical alerts.
- L1 / L2 / L3: Setup on-call support process for L1 / L2. L1 support includes interacting with customers. L2 support manages the tickets routed to them by L1 and helps troubleshoot. L3 is the last line of support and usually comprises a development team which addresses the technical issues.
- Degree the software protects information and data so that people or other products or systems have the degree of data access appropriate to their types and levels of authorisation.
- This family of characteristics includes confidentiality (data is accessible only to those authorised to have access), integrity (the software prevents unauthorised access to or modification of software or information), nonrepudiation (can actions or events be proven to have taken place), accountability (can user actions of a user be traced), and authenticity (verifying the identity of a user).
- Auditability: Audit trails track system activity so that when a security breach occurs, the mechanism and extent of the breach can be determined. Storing audit trails remotely, where they can only be appended, can keep intruders from covering their tracks.
- Compliance: Adhere to data protection laws like GDPR, CCPA, SOC2, PIPL or FedRamp.
- Privacy: Ability to hide transactions from internal company employees (encrypted transactions so even DBAs and network architects cannot see them).
- Authentication: Security requirements to ensure users are who they say they are.
- Authorization: Security requirements to ensure users can access only certain functions within the application (by use case, subsystem, webpage, business rule, field level, etc.).
- Durability is the solution ability of software’s serviceability and meet users’ needs for a relatively long time.
- Replication: involves sharing information to ensure consistency between redundant resources to improve reliability, fault-tolerance, or accessibility.
- Fault Tolerance: It is the property that enables a system to continue operating correctly in the event of the failure of one or more faults within some of its components.
- Archivability: Will the data need to be archived or deleted after some time? (For example, customer accounts will be deleted after three months or marked as obsolete and archived in a secondary database for future access.)
- It has become today’s buzzword when describing a contemporary software method. An associate agile team could be a handy team able to befitting reply to changes. Modification is what software development is highly abundant.
- Maintainability: How easy it is to apply changes and enhance the system? — Represents the degree of effectiveness and efficiency to which developers can modify the software to improve it, correct it, or adapt it to changes in environment and requirements.
- Testability: how easily developers and others can test the software
- Ease of development: the degree to which developers can modify the software without introducing defects or degrading existing product quality
- Deployability: The time to get code into production after committing the deployment time.
- Installability: Ease of system installation on all necessary platforms.
- Upgradeability: Ability to easily/quickly upgrade from a previous version of this application/solution to a newer version on servers and clients.
- Portability: Does the system need to run on more than one platform? (For example, does the frontend need to run against Oracle and SAP DB?
- Configurability: The end users can easily change aspects of the software’s configuration (through usable interfaces).
- Compatibility: Degree to which a product, system, or component can exchange information with other products, designs, or members and perform its required functions while sharing the same hardware or software environment.