Cloud computing has come to the front of application development with explosive growth. It is no wonder with things like multicore CPUs, tons of storage and excellent uptimes that many developers want to create applications for the cloud. However, what this creates is a new model for designing and developing code so that it will perform at its best in the cloud environment. We need to work on addressing the demands of computing in a cloud-based environment, and in this article we will look at the four areas that developers should focus on for cloud applications to work at their best.
There are four major areas programmers should look at when planning a cloud application:
As we look at each of these areas in-depth it is important to note that as we write code to maximize the benefits of each of these areas, we can reap significant benefits in the cloud’s multi-processor and distributed architectures.
Atomicity is the idea of atomic code, which has one specific and clearly defined purpose. In OO development this is also known as cohesion. Atomic code has a single responsibility where each class and method has its own job and concern as well as a complete disregard to the order of execution. This code should be self-contained and have no dependencies. This doesn’t mean that you can’t use other libraries but you should not have any level of interdependencies between method calls.
Atomic code should be concise to prevent it from losing its specific focus. Usually, if a method is long-running it is completing more than one task when broken down. If your method is doing multiple things then you should break it into separate atomic methods or possibly even separate classes to make the code function better when executing across multiple processors or threads.
Atomicity comes down to the environment in which it will be run. Code that will be executing in the cloud environment will have a clear advantage over how it executes and will be more flexible in the distributed environment if it is already broken down into steps. This also gives you more control over issues of reliability and problem resolution since distributed environments use compensating tasks to check for failed calls and make corrections. If your code is atomically written, then you will know exactly where the problem lies when you need to check it.
To conclude this section, we should be writing code that is independent in its operations, that do not require a specific sequence to execute and that can be executed in parallel. Doing so will gives us a greater amount of concurrency in our distributed applications.
The concept of statelessness is simple: a stateless object does not hold information or context between calls on that object. Each call on the object will not rely on previous calls or will be part of an ongoing conversation. This does not mean that objects do not use data or context but rather they do not hold this information over multiple method calls.
There are a number of advantages to being stateless in the cloud. Looking back at the previous section, we saw that cloud applications often need to execute the same sections of code in parallel or execute methods regardless of the order they were written. Stateless objects can be called upon by multiple callers and have their call satisfied. This creates a situation where the cloud environment is free to call upon or use any instance of that object to get the job done.
Using stateless objects can also help scale your application in the distributed environment because the work can be balanced onto whichever machine is ready to do it since a specific object instance is not required. You do not have to worry that the contention of a single instance object has caused deadlock, starvation or race-conditions. The idea here is to reduce the dependence of the application on one “golden” object that may be wanted by many concurrent calls. This ultimately creates a scalability bottleneck.
Statelessness lends itself to load balancing since the cloud environment would be free to use any machine to get the work done and whichever machine is currently the most available would get the job. Remember that statelessness can also lead to greater availability and reliability since the cloud has a self-healing capability when machines go down due to hardware failures; the work can go on somewhere else.
To conclude this section, remember, stateless code should allow your application to execute better across multiple processes, remove problems of concurrency that happen in the cloud and ultimately make your application more reliable.
Idempotence in computing is defined like this: methods or subroutine calls that can be safely called multiple times, as invoking the procedure a single time or multiple times results in the system maintaining the same state. This idea can also be translated as: the system is able to produce the same outcome every time, even if the event or message is received more than once.
The idea is to create code that does not perform destructive actions through method calls or events. This way, no matter how many times the message is received, the result will always be the same. Writing code this way can become more difficult when managing state, which is one of the reasons to avoid using state-based objects.
In the cloud, if your code is designed to be indempotent, you will end up with a lot of flexibility in the way your code executes in the distributed environment. Since most distributed environments expect failure, they are designed to work around it. You code should be designed the same way. Many of the benefits we have already discussed in atomic, cohesive and stateless code also can be found in idempotent code.
To allow your application to have the same reliability that the distributed environment helps to provide, you have to expect that executed steps or method calls will be interrupted at some point. In the event of these failures, you will want the distributed environment to repeat these calls so that processing can continue in your application. Idempotent code should allow the repetition of actions for these circumstances without the worry of bad data, destroyed objects, incorrect state and without dependencies.
In the past, writing parallel code was a specialized task since most of us did not have access to the hardware to run such code. Those days are long gone. Now, new workstations as well as servers have the capacity to run multiple threads and processes which can be utilized by our application.
As the industry moves towards more powerful computing platforms, our programming languages have evolved to handle these tasks. Many languages have introduced tools to help with writing or running code in parallel and new constructs are being added to aid in this development. The use of ideas such as immutable objects which can enforce data safety across threads and functional languages that encourage the base principals we have previously discussed are appearing to help make parallel execution simpler.
Most cloud environments will allow you to run code in parallel without special language constructs (although they exist for most languages) and many of these environments will take advantage of multiple CPUs to compute in the most efficient way. However, it is not always clear which code should be allowed to run in parallel so tools have been developed to help you.
In this article, I have discussed the various principals that you should be striving for when writing distributed cloud-based applications. Through the use of these techniques you can make your code cloud-ready and multicore friendly so that you can reap the benefits of the platform. While these ideas may be a strong paradigm shift from how you currently code, transitioning to a distributed environment frame of thought doesn’t have to be a difficult task and can often result in an improvement in your programming ability when writing non-cloud based application since you are now actively looking for ways to improve your code’s reliability and functionality.