Architecture
Sodacan is a scalable application framework. Sodacan encourages compile-time type-checking. Encapsulation is redefined: Simply put, rather than a large data layer and a large behavior layer, Sodacan encourages a large number of small containers each having data and behavior combined. How small is small? How about one customer, one user, one shopping cart, etc. That's small. But it is just right when describing a business flow.
The fact that systems have been separating code from data has been well established for several decades. But here's a thought: That separation is probably the biggest vulnerability of them all: Application code which is responsible for protecting access to data and providing an audit trail of transactions can all be bypassed by a DBA with some simple SQL. That carefully written permission and message encryption are out the window. The finger-pointing is where it starts.
In Sodacan, we stick them back together and it will be disciplined. How it does this will be described shortly.
But, before reading further: If you want to keep your data and the behavior that accesses that data separate then you can stop reading now. Although Sodacan can certainly operate that way, it probably would not be a good fit.
Also, if you've looked at or used popular mircoservice architectures, they generally suggest picking the right size of a service. In particular, services shouldn't be too small. Sodacan probably targets a smaller “service” than that because it is based on real-world entities. I did some work in healthcare IT and I found it interesting that clinical folks, probably because of their training, deal with concrete examples: A specific patient with a specific diagnosis, taking a specific drug, etc. A software engineer is more likely to think in abstractions: Patients, diagnoses, and drugs. Again, a vestige of their training.
As an application engineer, I would prefer it if I could bend to the client's way of thinking rather than the other way around. So, Sodacan is not going to change the business model to suit the technology. Sodacan does impact some of the design patterns you may be using. They will be described as we go along.
Concurrency
There is a pretty high cost of managing concurrency in many application frameworks. Most frameworks offer various ways to essentially hide concurrency issues using abstraction layers. For example, most frameworks do a good job of hiding database access from application code. But the application programmer is still likely to spend a good bit of time designing and implementing SQL or NOSQL queries because the database is managed separately from the application code. At a minimum, an application programmer needs to be concerned with a data manipulation language (SQL) and a procedural language (Java). Invariably, there is a tug-o-war between the two disciplines.
Another dimension of the concurrency challenge is related to commit and in particular two-phase commit. This is a construct that allows the developer to say: “I want the entire world that I need to interact with to freeze while I conduct my transaction.” Now, when does that occur in a business process? Never. And, further, that whole mechanism doesn't apply to workflow process. Those have to broken up into little spurts of transactions in such a system.
Don't get me wrong: There are business transactions that behave like this. Double-entry bookkeeping for example. Or, a trial balance on a batch of journal entries.
But, the traditional transaction semantics break down in highly concurrent systems. A DB vendor might say: “You've designed your system wrong” when trying to model a business process that occurs frequently. Or, they might say: You need to serialize this inherently parallel business process because our product only supports N parallel queries at one time" (and it's a surprisingly small number).
So,the rules for Sodacan are simple: Every single actor (not class of actor by actual instances) should thing of itself as acting totally alone. Nothing to coordinate between Actors. [Yes, the underlying implementation is a bit of work, but that's not what the business process needs to worry about.
Denormalization
Sodacan is no relational database. Quite the opposite. A simple example: A shopping cart, while active needs some product price information. Once the cart is submitted, the product price info should be frozen. So, a query against a product price table would no longer apply for a snapshot of the finished shopping cart. In Sodacan, this situation can be handled using a subscription to each product price which keeps the shopping cart up to date without having to join with the product price table each time it's queried. The subscription is cancelled when the shopping cart is submitted thus freezing the shopping cart price information. The shopping cart in this case would never need to query the product price table. It would always be local and up to date.
Observability
Statistics
Need a table of the available statistics but maybe not here.
Message as audit trail, especially history
Actor Model (Background)
Ignoring any specific implementation of actor model for a moment, the essence of actor model is:
- Actors run concurrently
- An actor processes messages; One at a time
- Actors send messages to other actors
- Actors can create other actors
- Actors do not share state and do not talk to each other without using messages.
Actors are a way to represent real-world entities. Actors are more constrained than microservices and more likely to reflect application elements than infrastructure elements. In short, Sodacan Actors are better at reflecting real-world business operations.
Sodacan Design
Sodacan exploits the Actor model and adds some additional features:
- An Actor has a permanent identifier, an ActorId
- Where an Actor instance executes is transparent and portable
- If a given actor has persistent data that it “owns”, then that actor will be the only “source of truth” for that data.
- Sodacan stores Actor state durably.
- [future] If desired, Actor behavior (code) can also be distributed by message. This feature makes it possible to avoid a shutdown or even a rolling upgrade when behavior changes. For example, a payroll system might rollout behavior changes frequently. Such changes can be audited in the same way as any other data changes.
Why Actors?
An Actor model provides the constraints needed to achieve a specific objective: Imagine one-whole-server for each business entity. One for each employee. One for each customer. One for each product in the warehouse. Thousands or millions of little servers. Maybe about the size of a matchbox. Or, a sodacan.
You'll notice a parallel to what today we call a GPU, which is made up of a lot of little risc processors. Limited capability but real fast. In the not too distant future they will likely be full servers with storage and communications ability. You may also notice a parallel to what happened years ago in disk storage technology: Big expensive disks were gradually replaced by large arrays of smaller, less expensive disks.
Now, one computer per actor may seem fanciful, so in the meantime, we can design systems that reflect the future of computing and will facilitate the transition to that future with minimum if any disruption.
In any case, the goal of Sodacan is to exploit the availability of vast numbers of low cost, smaller servers. Maximizing parallelism.