Software Design & Architecture – Part 1: The Core
When designing new software from scratch, it’s easy to get drawn into the detail of a single piece, especially if you’re a developer by trade. Consideration has to be given at every step, to how each of the pieces will fit together, and so it’s important to plan, starting at the core.
The core is separated from the rest of the application, in a place that is completely secure, isolated from everything else, and with fully separated concerns. The core is never asked to perform a task directly, a very important part of this style of architecture.
When designing our new software, we need to understand what our physical entities are (if there are any at all), so that we can model them for communication purposes. Consider we’re designing a new home automation system, and we want to understand what our physical entities are:
- A user – Someone who wants some information, or wants the system to perform an action
- A device – This could be a physical mechanical device like a switch, or simply a sensor
That basically it. Our entire system, no matter how clever it gets is simply a way for users to interact with devices.
Now we need to decide how: touch, type, voice? These can be intrinsic to the devices, but might also need to be controlled from a central hub.
So that’s the first part of our system: a hub (the core) which takes input from a user, and sends output to one of more devices. We don’t know what or how yet, just that it does.
So let’s examine our two entities in a little more detail.
To our system, a user is simply input. The system cares not who they are, or if the previous input came from the user giving the current input or someone new. The user may care, but the system does not. This is important to remember, because when given an instruction to a device, it should come from the system, and not from the user.
Imagine a room within a room. and in that inner room is a box full of secrets. In the outer room there is strict security, checking credentials. In the inner room there is none. Anyone in the inner room is free to look inside the box of secrets, without anyone questioning them. This is how the core should be. Any instruction from the system to the device should never be impeded by security.
Going back to the room analogy, imagine if we wanted to make sure that everyone looking in the box of secrets really was allowed to, so we add more security on the inside. If the security on the outside is really doing it’s job, all we’ve really done is added a redundancy, impacted the performance of our system as a whole, and duplicated an external system.
The correct way to achieve this security (back to our real design and away from the room) is to move the user request into a queue, and separate the queue from the user with a security layer. This allows us to design a queue which can have strict entry requirements.
This then gives us our second part of the system: a message queue.
User > Instruction > Message Queue > Core
We got here quickly!
Now let’s consider or 2nd entity.
Unless we’re just talking about a series of switches or sockets, our devices are going to come in a number of “flavors”. Some may be switches, some sockets, some sensors, some virtual switches which control other code. Basically we’ll have input devices, output devices, or devices that are both. Thus we start to build some device characteristics. One of those characteristics will be the direction of flow of information, and the next will be how we are going to communicate that information.
Modern devices come in so many form factors now, and from so many different vendors utilizing so many different technologies that it can be difficult for newcomers to home automation to decide whether they want their system to be wired or wireless, RF (radio frequency) or WiFi. And not understanding the details behind these technologies, many consumers end up spending needless money buying the same brand product families to make sure everything is compatible. This is the whole reason for writing my own unbranded home automation system, allowing me to find a product I like and add it to my system regardless of who makes it or what kind of technology it uses.
Because of the nature of all of this, we need to create a common “device” that our system can send an instruction to, regardless of what type of device it is, and have the device disseminate the instruction and perform the required action. After all, this is a part of the design…let the things do what the things do, unless we need to interrupt them. This then gives us a branch toward our core interacting with our devices, in a “device registration” mechanism.
Without getting into any details about protocols, security policies, storage, or messaging, we have a basic understanding of our framework. We know that we need a system where we have 2 external entities (a user and a device) which we (the core) need to interact with to transfer a request for an action.
Okay, so we haven’t actually built anything yet, which is good cause if we screw something up, we don’t have far to go back.
I’ll leave this here and start writing part 2…