Cloud-Native Development just clicked for me
Tags: cloud, serverless, aws, beginners
Published: 2020-06-20 21:53:16

---
title: Cloud-Native Development just clicked for me
published: true
description: 
tags: cloud, serverless, aws, beginners
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/g8l7ulxht4ij66wln5ic.jpg
---

It is already 2020 and many companies are still debating what cloud development strategy they should adopt. I am conscious of how many of them still opt for building multi-purpose applications that can run on multiple clouds, while only a few really adopt a native approach for running integrated applications on the cloud platform. And while I can understand that cloud-native development seems like a sky-level risk (_am I putting all my eggs in one basket?_) I'll try to explain why this is a good (and inevitable) choice.

Writing multi-purpose applications that share code between different platforms is not new. The idea of _write once, run everywhere_ was the mantra during the late 90s but applying it to today's technology seems to be more harmful than beneficial. And I am not talking only about cloud technology. If you don't believe me, look at [what happened to Dropbox engineering team with their mobile development strategy] (https://dropbox.tech/mobile/the-not-so-hidden-cost-of-sharing-code-between-ios-and-android)

## The transition
While many companies start implementing their vision of cloud-integrated applications and services, it is an accepted (_yet temporary_) pattern to deploy these services outside the platform on any on-prem infrastructure. Why? Because they need to keep the business running while they implement this transition. They can't just wait 3 years to have all their systems migrated to the cloud.

By adopting this **bimodal strategy**, these applications and services are cloud-native at their default implementation, but still portable by applying isolated and well-documented changes to their source code.

Wait, why do we still require changes to our source code for portability and not implement those services with Kubernetes?

Well, because we want our default service implementations to maximize the benefits of the underlying cloud platform. Requirements are usually cost control, managed services, and live deployments (no maintenance windows) and that indirectly pushes you to serverless and cloud-nativeness. 

However, it is important that during this transformational period these companies mitigate but not eliminate cloud-nativeness to enable easy service portability outside the cloud platform.

## Why go cloud-native?

By writing code in a _standard_ way using the platform's defaults, we ensure we benefit from the full capabilities of the chosen cloud. Closer proximity to cloud features makes for simpler implementation. Conversely, biting the bullet to rewrite native code to address a different platform, while on the face of it a pain, is usually fairly straight forward and less costly

Common abstraction approaches invariably address the lowest common denominator, put a brake of innovation, and result in more costly and more complex solutions. That overhead will end up being more expensive than re-writing isolated pieces of code multiple times for multiple platforms.

Wait, re-writing all the apps and services code? Yes. Well, not all of it, only some very isolated parts

## How to mitigate?

During this transitional period, cloud-nativeness can be mitigated but not eliminated. And this is handled at component **engineering** level

### 1. Don't couple
First of all, don't couple your business logic to the platform. Although this seems pretty obvious, it is way more important than it sounds.

![don't couple](https://dev-to-uploads.s3.amazonaws.com/i/pdnew1o6zyjyo8fn90jq.png)

### 2. Write interfaces
Code your business logic to an interface. Again, nothing new, just _old school interface-oriented programming_. This is, separate functionality into modules that communicate via well known functional interfaces (e.g. interfaces that mean something to the consumer function, rather than being technical abstractions)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pgx99kqat2iq2j17me76.png)

### 3. Isolate the interfaces
Isolate code that accesses cloud services directly via SDK behind such interfaces and use dependency injection to instantiate the appropriate interface implementation at runtime. This is commonly known as _The Provider Pattern_

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/koid16tw0sn2ttvf6qf8.png)

Example:

- AWS has a service to provide hierarchical configuration information - SSM Parameters
- Design an interface that presents configuration data in a manner that makes sense to the application (a key/value map, perhaps with additional application-specific semantics)
- All consumers of configuration address this interface
- Write a module that implements the interface using the SSM APIs and translates the data into the format demanded by the interface, plus maybe has caching capabilities
- At application start-up, accept an environment variable naming the configuration data implementation to use.

### 4. Reimplement the interface
OK, so you want your cloud-native code to run on another cloud? No worries, just reimplement the interfaces for _that_ new cloud platform using the new platform's standards and direct access to services via new SDKs. Well isolated and documented changes, while the core business logic remains untouched.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k66i8g4wi4mr5dqsujm0.png)

More importantly, you need to have your application or service running on-prem? Even easier, re-write those interfaces using supported industry APIs (i.e. JMS, MQTT) and de-facto standard providers (i.e. Hibernate for JDBC).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/78bk2tvj7tn1w7f2v6qi.png)

## Composing Cloud-Native Software

It is clear and recognized that access to platform services via industry APIs or de-facto standards are more portable by nature. However, we can't just wrap every direct access to cloud services with an HTTP interface (API).

Why not?

**Again, by writing code that does not leverage the underlying cloud platform’s defaults, we would take an overhead that we would not have to worry if we stay with these widely used cloud technologies. This overhead will end up being more expensive than re-writing isolated pieces of code multiple times for multiple platforms**

However, it is important that every component is exposed through and standard HTTP interface. This is how we will compose cloud-native software.

- Modules are composed by combining different functions
- Components are composed by combining different modules
- Systems are composed by combining different modules
- Solutions are composed by combining different systems

This principle rolls up and down, [and it is one of the most important guidelines to build modern software](https://medium.com/javascript-scene/composing-software-the-book-f31c77fc3ddc).

Back to our main topic, I think that cloud-nativeness risks are mitigated above the component level.

## Summary

Cloud-native development is faster, cheaper, simpler, and more productive. In the _unlikely_ event of a change of cloud or platform provider, portability is obtained by identifying very isolated places where a code change is necessary:

- a new interface provider here,
- a new event format transformer there,
- a slightly different container configuration elsewhere

Even easing any necessary on-prem deployments on-prem. Most services provided by clouds are available off-cloud, though usually at a greater overall cost. Just use industry APIs and de-facto standard frameworks.

In short, exploit modularization, interface-oriented programming, dependency injection and you are good to go. Just (age-old) good programming practices!

(Credits to [Billy Huy](https://unsplash.com/@billy_huy) for the cover picture)