There are 3 major concerns when writing a good software:
What do they mean? Let's explore their definitions.
Reliability is the ability of a program to tolerate faults.
There are three different kind of faults:
- Hardware faults
- Software faults
- Human faults
Hardware faults are caused by machine errors. A storm in the data center where your server is and a failed hard disk are examples of machine-related incidents. In general, they are outside of your control, especially if you use third-party providers like AWS. To reduce hardware faults, you can regularly service your servers (if you own them) or have a backup servers in case your main server provider is down for a long time.
Software faults are code-related errors. A code that is written under the wrong assumption and a third-party API returning 404 are examples of code-related errors. To reduce software faults, you can increase your code coverage and have a fallback plan in case the third-party API becomes unavailable.
Human faults are user errors. You accidentally setting up the wrong environment variable values and users interacting with your software in a way that's not intended are examples of human-related errors. Human faults are the leading causes of unreliability. In general, design a software to make it harder for developers and clients to do the wrong thing and easier to do the right thing.
Maintainability is about making life easier for the future developers.
To me, the word "maintainability" sounds inferior compared to other buzzwords like "scalability" or even "fault-tolerant", but it is equally as important. The majority cost of a software is in ongoing maintenance, not in its initial development. It is very, very important to write a maintainable software.
A maintainable software must adhere to these 3 principles:
- Simple (low complexity)
To make a software operable, you can:
- Run continuous security patches
- Have a good monitoring of the software health endpoints
- Do a thorough testing and good deployment tools
As your software size increases, its complexity also increases. A highly complex software slows down the development time, thus lowering maintainability and increasing maintenance cost. To keep softwares simple, you can:
- Maintain a reasonable number of states in stateful components (break them apart into smaller components once it becomes sufficiently large)
- Eliminate unintended consequences and unexpected interactions
- Create a good, clean abstraction
Your software is always evolving. There is no such thing as a static software. Client discoveries, regulation changes, project size increases/decreases, etc. These are things that you, as a developer, can't avoid. To make it easy to make changes, you can:
- Prevent decoupling
- Make classes open for extension
- Have few dependencies
Having a good scalability means that your system can work reliably in the midst of increased load.
When your startup is growing, here are some questions you need to ask questions like:
- What would happen to the database if you go from 10,000 writes/min to 100,000 writes/min?
- What would happen to the front-end server if the number of concurrent users increased from 500 to 5,000?
Essentially, if the load is increased tenfold, or even one hundred fold, can your system still handle that without compromising performance?
Load is an important keyword in scalability. A load can mean different things:
- Number of requests to a server
- Number of concurrent user
- Read/write ratio
- Cache hit rate
The two main ways to scale are:
- Vertical scale
- Horizontal scale
Vertical scaling is increasing your machines capacity by upgrading the hardware. If you need more storage, you can get a hard drive with higher storage capacity. If you need more RAM, you can get a higher RAM. Vertical scaling is typically easier to do, but can quickly get expensive. Doubling the RAM, at some point, will cost you more than twice the price. Quadrupling the storage, at some point, will cost you more than four times the price. This is because price doesn't scale linearly with computer parts. There is also usually an upper limit on how high of a capacity you can have.
Horizontal scale is when you're adding more machines to your system to distribute the load. If you need more server bandwidth, you don't upgrade your server, you add more servers into the load balancer pool. Horizontal scale is harder to execute, but overall is cheaper than vertical scaling.
Reliability is writing a fault-tolerant software. Scalability is preventing performance degradation when facing increased loads. Maintainability is ensuring that present and future developers can understand your system well.
These three are the main ingredients of writing a good software.