Following my work on various web applications in Django/Python and Spring/Java, I thought it would be beneficial to summarize some of the principles I have found that are very useful but seemed to be ignored or just plain unknown. The focus will not be on principles such as KISS or Convention over Configuration but instead on the uncommon principles. There are plenty of material online on the general principles of web app development (a.k.a. please don’t penalize me for not including your favorite, popular principle…), this is a good one from Atlassian. Hope you enjoy the article!
Perfect the most Frequent Use Case or the 80/20 (Pareto) principle
I am going to be just a teeny bit radical but YOUR FEATURE LIST DOES NOT MATTER! It does not matter if you have features W, X, Y, Z if the majority of your users (most likely to be 80%) only use feature A. Ask your users what they care about and WHY they use your application, they will know exactly what to say. If you can not or do not have the ability to ask your users, here is a quick fix. Ask yourself “Why am I making this app?” If your answer contains any of the following phrases, you are doing it wrong: “cool”, “does X”, “has Y”, etc… If you are having trouble with answering “Why?” properly without resorting to a sentence that includes what your competitors do or something technical, watch this video.
You should not complicate your solution to solve edge cases, your focus should be on your core competency. This may be obvious but seems to be commonly ignored in the rush to build more features into the web app. This is not only bad for development purposes, but it is also terrible for the user experience. In trying to add more and more features, you will often confuse the users of your web app that you are trying to convince to pay (more) money for your application, quite contrary to your intentions.
Once, you have identified your most frequent use case; there is a classic theory available to help you quantitatively determine how a new feature or an optimization will impact your users. The theory (more of a law) is called Amdahl’s Law. This law is famous among embedded and computer engineers, but I rarely see it used among web developers explicitly. A simple explanation is that the performance improvement gained from a change is limited to the fraction of time the improvement is used. The formula is simple:
Example: Number of Clicks
Your web application’s most common feature is used 76% of the time your users are on your site. You want to take advantage of this fact and reduce the number of clicks the user has to make from 4 to 2 to increase user satisfaction (if you charge per use of this feature, this will help you make more money as your users will use it more often and faster ;) ). The overall speedup is calculated like so:
Parallelize on Multiple Levels
With multicore processors being the norm for quite a while and with the emergence of cloud computing, being able to take effectively parallelize your web app can help you save money and optimize your response time (or other metrics you use). Parallelism is available on many different levels, to actually take advantage you have to operate on many of these levels (and you might as well use Amdahl’s Law to calculate where you will have the most anticipated speed up before you get to work). Web app developers, you are extremely lucky nowadays with services like Heroku that effectively will do this for you at a price. Otherwise, if cannot afford it or do not want to use services such as Heroku, I hope you will find the following helpful.
Storage Level Parallelism
If you aren’t able to afford SSDs, ensure you setup your disks with whichever RAID configuration you feel comfortable with, e.g. RAID 10 or RAID 5.
Database Level Parallelism
There are two ways to parallelize at this level; first, you can parallelize the whole system e.g. by having a master-slave setup or by using a completely distributed database, second, you can use database specific for parallelizing your queries, e.g. Oracle Parallel Querying (check your database documentation).
Server/Application Level Parallelism
At this level, the parallelism that you can achieve depends very much on your stack. Nonetheless, it’s worth the time and effort to experiment with different application containers or servers to figure out which one offers the best parallelism strategy for your application.
Load Balancer Level Parallelism
The whole purpose of load balancing is to parallelize request handling to your app, not much you can do here besides set up a load balancing solution, HAProxy is an excellent one, so do it!
The idea is that the majority of your application execute instructions or use data that are either spatially or temporally close to each other. Hardware engineers and compiler writers exploit this to it’s utmost, e.g. caching memory on the CPU or scheduling memory load instructions in bulk if they are close by. There is no reason this principle cannot apply to your web app!
Temporal locality stands to say that instructions or data that are recently accessed will most likely be accessed again in the near future, i.e. the reason we use caching. Before we move on, though, let us go back to the common use case of your application and see if we can extend this concept a little further. Reword the principle to say: instructions or data that are recently accessed also indicate companion instructions or data will be accessed shortly. Say your common use case requires multiple steps/actions on different pages with multiple queries, and you know that the vast majority of your users will complete these steps (i.e. you are a lucky soul who works on business apps where people are paid to use your web app), you have a pure opportunity to exploit temporal locality. You can click immediately on the initiation of the first step cache the data/steps/code/HTML (whatever) for the rest of the use case for speed optimization.
Spatial locality stands to say that instructions or data which are stored close to each other will most likely be accessed near each other in time (not referring to geographic locality). This principle is slightly less obvious to apply and will depend on your application, however, here’s an example where it can be useful. Say you have a calendering feature in your web application, and you allow your users to store records based on the time they will take place on this calendar, you can most certainly expect that records in your database stored next to each other will most likely have been stored by the same user bulk entering items in his calendar (this will depend on your application) and thus you can quite reliably predict your database read access and improve it.
Feel free to comment and offer additions.