
Serverless is more than just a run-time for your code. It's a suite of cloud provider managed services to help fine-grained, event-driven applications best utilize the cloud. Automation is an integral part of building serverless applications and often the same functionality can be achieved from application code or through a platform feature. Take sending a message from a Lambda function to SQS as an example. You could do this by writing code, utilizing a client library like boto3 or you could configure a Lambda Destination. The latter approach is preferred because it utilizes the cloud platform and separates application topology (which component talks to which others) from the application logic. Interestingly, with AWS CDK you can configure the Lambda destination using the same programming language that you used to write your application code.
You can improve the design of your serverless application by replacing application code with automation code, while using the same programming language.
That's what we call Refactoring to Serverless, based on Martin Fowler's definition of Refactoring as a popular coding technique to improve your application design:
A disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior
In our case, the refactoring moves code from the application to CDK automation. Other refactorings might improve the overall application design. Let's look at the example in more detail.
Lambda code often performs tasks that could be more easily and more reliably performed by using a platform feature. For example, the following code was taken from a public GitHub example:
queue_name = os.environ['SQS_NAME']
sqs = boto3.resource('sqs')
queue = sqs.get_queue_by_name(QueueName=queue_name)
def handler(event, context):
...
response = queue.send_message(MessageBody='world')
This code isn't just unnecessary, it also hides the application's topology in application code and environment variables. You would not know that this function connects to the SQS queue unless you inspect the source code and the value of the environment variable.
The refactoring replaces this function code with a Lambda destination. By extracting the code, the dependency between the functions and the SQS channel becomes explicit in the automation code:
new lambda.Function(this, config.bankName, {
runtime: lambda.Runtime.NODEJS_14_X,
functionName: "MyFunction",
onSuccess: new destinations.SqsDestination(sqsChannel) } )
You could now, for example, use your IDE to search for all references to sqsChannel to more easily understand dependencies. You can find the full description of this refactoring at Extract Send Message
There are multiple benefits to refactoring your solution to serverless:
Because of these benefits, refactoring should be an integral part of serverless development.