When you want to start something, you would need to convert your idea to a well designed, viable and executable plan. The process of doing this can be called as architecting and the it can vary depending on the idea, time and resources available. I thought of sharing my own experiences in architecting applications over the years and what I personally feel is the best way to go.
Start small, but think BIG
This is one of the mantras of agile practices where you are asked to start small and progressively build on what you have. While this is definitely effective, you would need to plan your architecture thinking of the future well in advance. You need to make sure that architecture is adaptable to change in the future if needed without much effort.
This is important because, while you can progressively develop on what you have, changing the architecture of an existing application is always painful if you have not planned for it well in advance.
Architect your application in such a way that the various components in it can be moved around and recomposed like Lego Blocks. I would always recommend a black box model which is the most simplest and efficient model if used correctly. Take an input, process it, give an output while abstracting the details and complexity to people who use it.
That is, they should not worry about how a lego block is made. Their focus should be in putting these lego components together to get the expected final outcome making things well organized and reusable. This is why microservices are hugely popular since it follows a black box model, acts like legos abstracting the details to everyone who use it.
Separation of concerns
This is very very important and I can’t stress enough on why you should take care of this when developing an architecture.
Separate the view, data, controllers/business logic and other relevant layers thus allowing portability, manageability and scalability.
For eg. If your database is not performant, you can always migrate data to some other database which provides better performance but using stored procedures for business logic brings you to a position where you are bound to a single database vendor since it becomes a very difficult job to migrate. Also, writing business logic in middle layer is always better since you can scale it horizontally as much as you need while the database layer may be pretty rigid when it comes to scalability.
Don’t depend on specific libraries or vendors for your architecture. Try to be generic as much as possible and be adaptable to change. This will avoid vendor lock in which is very dangerous and can sometimes be a huge hindrance to your product growth.
For eg. using an ORM like Sequelize can help you since you can migrate your database to MySQL or SQL Server or PLSQL or any other SQL based database without changing your queries since it takes care of the generalizing for you.
Business & Technical goals
While developing an architecture, it is very important to keep in mind both the business and technical goals of the architecture and design accordingly. Is the main goal increasing revenue or improving retention or something else?
While an architecture model can satisfy the technical goals, it can end up too costly and hence may end up as a challenge to business goals. So, a balance needs to be established between both the business and technical goals.
Designing the database models can sometimes help since it gives an idea about the data boundaries, relationships and other parameters which can help a lot in architecture decisions.
These data models are in turn dependent on various business entities and this can help in realizing the business goals through architecture.
It is very important to understand your boundaries before you start working on architecting a product. You need to respect the constraints you have been given and develop the architecture which would best fit the given constraints, be it time, money or something else. While respecting constraints is important, it should not be a hurdle to your creativity.
Fault tolerance & backups
You can never ever guarantee the utopia-like situation in your application. Things wont remain perfect always and faults are bound to happen. So, you need to plan for that well in advance and device strategies to handle them in a graceful and proper manner.
You need something like circuit breakers for your application which does not give room for devastation in the event of faults in your application. The best way to do this is by developing user flow diagrams and handling error cases in each and every stage of the flow.
Strategizing ways to backup data is also very incase you want to recover after a fault to some previous state/snapshot. It is also very important to consider geolocation into account while doing backups since faults need not be always at a software level. There can be natural disasters or other calamities which can cause faults and having backups at different locations would be very helpful.
It is very important to understand what fits the best for the scenario rather than blindly choosing tools and technologies thereby hugely impacting the performance. For instance, if you want to get the complete juice out, it may not advisable to use REST APIs for internal service to service communication due to the extra latency it adds through the headers while it is well suited for external networks. So, you can think of something like RPC which can do internal communications much faster than a REST call.
Ultimately, the point is, choose the right tool for the right job and it all depends on the use case.
It is very important for most applications to maintain a good up-time to avoid loosing business. You would need to devise strategies to reach close to 100% availability. This is most often made possible by having fail overs, software and hardware load balancers and using orchestration and configuration management tools which helps you maintain the desired state configuration at all times thus offering availability at all times.
If a node is to be taken down for maintenance, you can always switch the traffic to a clone till the maintenance is over and this switching can be handled by the load balancers as needed.
You may need to forecast the consumption of your product gathering relevant details and make sure that your architecture would satisfy the growing needs without much effort which, in technical terms is called scalability.
In the modern era, most of the technologies/tools lay a lot of emphasis on this criteria making sure that things can be distributed from the get go. For eg. Containers and serverless architecture have become the buzzword today and rightly so because of the power they have in allowing your applications to scale up or down depending on your needs rather than investing on a lot of money upfront or paying for the resources which you may not even use.
This is often overlooked when developing application architecture and treating it lightly can lead to devastating blows.
Thinking of security during the architecture stage would help in overcoming faults early on without having to worry much about it at a later stage of development.
Don’t leave the doors and windows opened unnecessarily, and where opened, make sure that you leave it opened only for authorized use. Also, make sure you devise ways to log activities where needed which would be helpful in case of security incidents.
Question every decision
It is very important to question your own architecture to make sure you have validated all possibilities, and are unbiased on the chosen architecture.
- Why should I do this?
- What if I don’t do this and what if I do?
- How would I go about this?
- Are there better ways to do this, and if so what are they?
- Would this be a scalable, secure, performant, available and fault tolerant? If not, how would I achieve all those criteria?
These are just some of the questions you ought to be asking. The more you question yourself, the better it is.
Wear different hats
This is a lesson I have been taught over the years. You need to think of the architecture wearing different hats. The hat of the user, developer, architect, designer and also from the operations and security standpoint. While this is very difficult to do when you start off (You often tend to look the architecture as a developer when you are supposed to see it as an end user), it comes with practice.
Just having a single field of vision is not good enough when you architect applications since it is going to impact different type of people differently. If you find it difficult to do it, you could also try coordinating and validating your architecture with multiple teams/stakeholders before you go forward with your decision.
Define clear rules and constraints
While architecting is just one part of an entire equation, enforcing rules or restrictions on the implementation stage helps a lot in maintaining the same consistency and stability across the product among various teams. This helps a lot because giving defined constraints to people works better than doing rework or iterations towards the same thing which you had planned ahead of time.
It is very important since you would always have the need to convey your architecture ideas/decisions to others. This is often done using flowcharts, UML/ER diagrams, mockups, etc.
The main objective should be that the intended recipient of the blueprint should be able to understand the architecture end to end without needing your presence. This helps a lot both for big and small teams and can also act as a reference as you go through the different phases of your product.
Often, there might be stages where someone would want to compromise on the defined architecture and go out of bounds. This might be risky and may have a high impact on the product in the future. So, it is better not to compromise and rather re-evaluate the architecture to see how it can be modified to fit the new requirement.
Org structure adaptability
It is often said that it is always good to match your application architecture to the org structure so that it will be easy to execute the working.
Work distribution, execution and maintenance all depends on the org structure. So, in case the org structure is not adaptable to change, you may need to reshape the product architecture based on the org structure. If you are going for micro-services, you can find an article here on how to adapt your org structure for the same.
A good architecture should be robust but still adaptable for change, maintainable, scalable, secure, available and performant. It has no fixed structure since every decision made on the architecture front depends on the use case.
And yeah, I am leaving few links below which are amazing resources to get yourself upto pace.