Service-Oriented Architecture( SOA) is not new. Microservices which are a specific flavor of SOA are the default architecture you will find out in digital products. I’m not sure if Microservices will be here for much longer. However, thanks to the silicon valley, companies can be structured in 2 organizations(Which is a good thing IMHO). Product and Engineering organization. An engineering organization means that you create software for your product engineers to be more productive and focus on the product and improving the user experience. Engineering organizations have different ways they could be distributing software. Software distribution is a fascinating theme for me. There are several ways we can distribute software however we often dont consider other distribution models. As your company grows and depending on your business segment you might have several specializations insider engineering like Data Science, Security, Big Data, Architecture, Storage, Mobile Devices, and so on and on. IMHO it does not matter the kind of software specialization we are not limited to binaries.
SOA It’s all about Services
SOA only talks about Services. Services are 1st class citizens and if you want to reuse you do it via services. Product organizations leverage Services however it’s very common to find engineering organizations being too much binary, I saw it so many times. Binaries are not wrong if you are very careful about dependencies(most of the time people are not). However, there are other distribution models beyond binaries. For instance, a model that is growing a lot nowadays is the Side Car pattern. Besides sidecars, you could rely on Services. Services dont need to be a consumer only via APIs or JARs or binaries, services can be consumed via generic UI or even a generic Jenkins Job.
One important thing that Services provide is abstractions. Meaning you dont need to CODE or you dont need to configure it a good abstraction if done the right way. Within a remote service interface like API/REST, UI or Jenkins job is possible, with binaries is not possible and often results in lots of coupling.
Issues with Binaries
By definition binaries are “EMBEDDED” meaning you need to have them on your side(classpath). Having binaries on your side means you get all side effects like Configuration, Schemas, 3rd party dependencies. By nature, binaries are much more coupled with the remote services. +10 years ago I remember when I was in a big international SOA Project. Then we had an idea to have EMBEDDED Services. Since all our SOA Services was written in Java we just important the jars in the target/consumer project and thats it you have an embedded service and it works. There was a great performance benefit for killing the remote call however it resulted in several other issues like:
* Much more difficult to configure since the jars had to have the configs our you would duplicate it.
* Dependency hell — since 3rd party dependencies were brought put there were jar conflicts.
* Potential Coupling — Now there is noting blocking developer to use non-contract classes(contract by accident will happen eventually).
* Difficult to upgrade individually: If you change the service need to change the embedded deployed service as well — which was always hard.
Services provide abstractions. Service Abstractions are potentialized by remote interfaces like REST/APIs, Generic UI/Jenkins because:
* Natural Hiding: Since you are “remote” or at least running the code someplace else.
* No contract By Accident: It’s basically impossible for the consumer to use anything beyond the public contract. When we think about the binary model, it’s every use to couple beyond the public contract.
* Easier to Scale: as you have control over how you operate your solution it’s easier to scale and provide a better experience and abstract that from consumers.
* Easier to Maintain: Since we are exposing less it’s much easier to upgrade the underlying operating system, data stores, code, languages, libraries, or whatever aspect of the solution besides the contract.
* Easier to Reason about it:
Service provides many benefits, they will always be less optimized as a specific solution however they often make more sense and provide a stable way to the company to build products and other services on top of each other which is how the internet works and how companies operate in the real world.
Operationalizing Services beyond Service Interfaces
SOA is not restricted to APIs(REST). You can do SOA with other interfaces / API, for instance, it does not matter the language or serialization format(XML, Json, Yaml, Protobuf, Flatbuffer, Avro, Parquet, MessagePack, whatever). Having said so, it’s also possible to provide generic UI’s and Jenkins jobs, which can be useful to consumer stateful services like Databases, Caches, Object Storages, DNS, Pipeline Platforms, Observability platforms, Stress Test / Chaos platform and much more.
If you take a look at AWS there are managed services like S3, RDS, Kinesis, and many others. These services abstract the operation, scalability, upgrade, patching, and security aspects for you. It’s possible to use some ideas and deliver internal services to your company. Netflix pig bank a lot in that idea and has several internal services(Similar to AWS managed Services).
You can do the same, therefore you can consider Operacionalizing services as an interesting distribution channel/model for your engineering solutions. Service approach means you have a centralized operation for those services, you can have different teams operationalizing different services.
Consuming a service does not need to be done always via an API. API(REST) has one big drawback when we compare it with Generic UI / Generic Jenkins job. They require you to CODE. In order to use it, you need to code. Sometimes coding is fine, as much as possible you should not require your consumers to code. For instance, think about a Database Backup Service. It could be a generic UI or Generic Jenkins Job you go there and just click in a button and thats it, you enable automatic backup for your application rather than have a DSL or Java API someone would need to use and run the code against it.
SDKs are fine, DSLs are fine. API’s are great. However, you need to consider whenever is possible to not require your consumers to code will be great and will increase productivity, abstraction and you will be leveraging more service orientation than binaries.
Double Down on Services
Remote Services with standard interfaces often could have performance drawbacks. For instance, REST Interface + JSON will be always slower than the LOCAL IPC call with a binary format for instance. However, trading performance for flexibility and abstraction is often a bad deal. Being remote often means you can scale beyond a single machine. Services are great as distribution channels because of the abstraction, easy to upgrade, isolation and it’s much easier to organized teams around it.
Services can be used for non-end-user products. Internal Services are an interesting and yet powerful solution to avoid inertia in software architecture. When you have a binary, if you improve your code, you often need to do a migration, which can be hard, tedious, risky, and expensive. Services provide a great abstraction and reduce lots of migration needs. Migration is a big concern because refactoring / re-testing all your consumers could be expensive and risky as you grow and have a big organization.
Internal Services make consumer life easier, compare DVD with Stream model for instance. DVD was like a binary JAR and Streaming is like an API(REST) or Generic UI or Generic Jenkins Job. There are several concerns that get abstracted by the service model. All models have tradeoffs, there will be cases were binaries are the right answer. IMHO we should be open to considering using more services whenever is possible.
Originally published at http://diego-pacheco.blogspot.com on July 4, 2020.