The distributed nature of enterprise applications should always point a software architect in the direction of Service Oriented Architecture (SOA). The basic problem that an enterprise application is trying to solve is:
A system where there are many users trying to access and modify the same data at the same time.
Consider a website and/or application that allows a user to purchase items using a credit card. This requires some sort of common data source:
There are a multitude of challenges when writing such distributed systems. Some of the more pertinent ones are
- Data Use – minimizing the amount of data transferred
- Security – ensuring that the user connecting to the data is allowed to view and/or modify that data
- Code Maintenance – trying to effectively build our application so that there is as little redundancy as possible
- Service Reuse – multiple applications and other services can connect to a service that provides common functionality, rather than having duplicate functionality in multiple applications
There are a few reasons that should motivate a software architect to minimize the amount of data transferred:
- Line Speed – The more data that needs to be sent and received, the longer the time required to send a request and receive a response
- Latency – if the data that the user is trying to access is geographically distant, each request/response’s time to process is compounded by this delay
- Packet Loss – In areas with unreliable network connectivity, the number of packets lost during transit is greater
These factors all contribute to a data delay that becomes very evident in production environments:
When connecting directly to a database, a task that a user would perform that would seem like a single instruction is more than likely several separate calls made to the database, especially if the database has been designed well (i.e. has normalized data). For example, let us consider a simple credit card transaction for purchasing several items:
- Call some third-party service that gives us credit card transaction functionality
- Insert a record into a transaction table with the amount of the purchase and link it to the user who purchased the item
- Link this record to each of the items that has been purchased, along with the price that each item was purchased for (prices change)
- Adjust the stock count for each item purchased, and possibly order new stock automatically if the stock count falls below a certain threshold
You might think, “My website will always be close to my database, that won’t be a problem!” What about scalability? Once our site has become the best thing since sliced bread and we have a billion users, we will have to start deploying the website on different servers around the world, and each one will be connecting to a single data source!
In the scenario described above, we will need some kind of security in place to make sure that people don’t do what they aren’t supposed to be doing. This requires some sort of security functionality on the client side (we don’t want to create separate database users for each and every one of the users who will be purchasing our products!). Consider the following:
The website, which will be running in our infrastructure, is fine. But what about our app? This will be running on every single machine where it is installed! That means that we will literally be placing our business logic, security functionality etc in the hands of reverse-engineers and hackers! Doesn’t seem like a smart idea to me!
In the scenario above, we are going to have to implement this business logic for every type of device that we target! That’s a lot of redundant work going on…
There is certain functionality that might be used in multiple applications in an organisation, for example, sending an email. Without SOA, the functionality to connect to validate email addresses, send mail to an SMTP server, as well as the storage of server credentials would need to be duplicated everywhere that email would need to be used. Instead, all of this could be moved to a service that each and every application and service connects to to send mail! When SMTP addresses and credentials change, bugs are fixed or new functionality is added, it is a simple matter of changing that single service’s configuration or completely redeploying it, leaving the many other applications using it none the wiser, yet still working.
If only there was a way that we could keep our data close to our processor, our sensitive functionality out of our users’ hands and reduce code redundancy! Consider this:
So what is actually going on here? There are a few things that you need to notice:
- We have created a data processor (Service) that is geographically close to our database
- We have removed our security and business logic from the client applications (website and app) and placed this functionality into a Service
- We have added a contract between our service and client applications
- The data delay still exists
So what has this actually achieved? Let’s look a little deeper…
We are transporting minimal data between our client applications and our service. Using our credit card transaction example, all we actually send over the wire is:
- The products the user wants to buy
- Their credit card details
The service then deals with the business rules and updating all of the relevant data in our database and calling the external services. This is perfectly fine because our data is geographically close to our service.
Our client applications now inherently share the security functionality and business logic that exists in the service – all that is necessary is to call the service with the contracts defined. Remember that the contracts don’t contain information about how the functionality is implemented, but rather what needs to be passed to the service and what will be returned.
If there are any business rule changes that need to be made, they only need to be made on the service side, provided that the contracts do not change.
Following on from the code maintenance, a lot of bug fixes that need to be made will not require a full client-side roll-out – we can simply re-deploy the service and the client applications will continue to run as is. That is a huge advantage – user’s will not be hampered by continuous updates!
Furthermore, due to functionality being moved out of client applications, the deployed software takes less time to download/update and uses up less space on the users’ devices.
The tiered architecture of SOA has great advantages for distributed enterprise applications:
- Application speed improvement and therefore better user experience
- Enhanced security
- Code maintainability improvement
- Simpler deployment processes
The only time that client applications need to change are when the contracts change. Supporting legacy service calls is possible, but it is much easier to avoid the complexity surrounding such functionality by supplying a version check contract that will never change. This way, when new client applications are available, we simply force our users to update their applications by denying them access until they do.by João Lourenço