I have been working in embedded devices business more than 5 years as a software engineer. Most of the times our hardware manufacturers provide a Software Development Kit for their reference boards. They are mostly Linux embedded devices.
The problem is most of the times we find the management interfaces (Web UI, CLI, SNMP ...) are tightly coupled with the database that stores persistent device configuration and also the interfaces carry out each one in their own all the operations to apply the new setting to the system. For instance when the user updates firewall state via Web UI the web server is performing itself the C system() function calls using iptables rules as argument. It makes us very unproductive because:
- We can not reuse cohesive components in new products. Specifications for new products are becoming more demanding and embedded system are costly to develop.
- Management interfaces are not consistent and code is repeated among them.
- As the code is tightly coupled and the abstraction is bad, the same goes for the tasks. It is difficult to parallelize tasks if the developer of a new functionality should know about the web server or the web server maintainer should know about a functionality implementation details.
- We can not test components but the whole system.
Sometimes the management interfaces call database API to store new setting and after that they call the same function which reads new functionality setting from database and apply the new setting in the system. I think it is not yet a good solution but I would like to hear opinions about this design.
Now we are trying to break up the software in responsible components we can reuse in new products. For instance we would like to use current embedded device services in new products, and also we would like to have user interfaces we can easily adapt for a new specification.
As software engineer I am aware about the consequences of bad abstraction, low cohesion and poor encapsulation in software design, but I don't have a good background in design patterns. This is our plan:
- Built a set of C functions for device services that can be called from the user interfaces, exposing an interface that hides all the possible implementation details from the use of the service. There will be functions to change the system time, to manage the GPIOs, to change the firewall state...
- This services APIs will take care about the persistence of its data by using the API of the persistence layer.
- The user interfaces will retrieve and set new settings using this API services set of functions.
- Each API of a service will expose a x_initialize() function so when system boots up a startup manager application can call this function for each service. This functions will retrieve settings for the service from database and apply them into the system by calling the other functions of its own service API.
I don't like very much the point 4 above because it looks pretty much like the situation we have now where the user interfaces store new setting in database and call a big function nobody know what this function does until it is seen the implementation details (and looking implementation detail of a function is a bad symptom for me).
I am looking for information about design patterns to reuse and separate concerns as persistent layer, user interface and the business or domain objects logic (I am not very sure I use well concepts as domain objects). I would like an explanation with concrete examples I can better understand.