Software architecture is the fundamental organization of a system embodied in its components, their relationship to each other and the environment, and the principles guiding its design and evolution [1]. Every embedded system should have a software architecture that guides the developers on what they are building. Unfortunately, it’s not uncommon to run across several pitfalls that get in the way of successful software architecture. In this post, we will explore five embedded software architecture pitfalls and how you can avoid them.
Pitfall #1 – Believing in evolutionary architectures
There is an idea that I’ve seen floating around development teams that there is no need to consider your software architecture before starting to code. Instead, there is a belief that a systems software architecture will miraculously evolve from nothing to a scalable, reusable, high-quality architecture on its own. Unfortunately, the belief seems to stem from a misinterpretation of ideas that came from the Agile movement. So, let’s set the record straight.
Software architecture is a road map, a blueprint, that tells coders how their code fits into the larger puzzle. A software architecture identifies the major components, their inputs, outputs, and interactions with each other. A characteristic of well-designed software architecture is that it is evolvable to meet the customer’s changing needs. However, in my experience, I’ve found that the most successful teams spend some time upfront working through their software architecture.
Spending some time upfront to figure out the pieces of the software architecture still fits with teams working within Agile methodologies. The architecture doesn’t need to be developed in a waterfall manner but can be designed and honed over several iterations as details and lessons are learned. A software architecture developed in this manner is generally more flexible and will be far more successful than a team hoping for architecture just to appear. Unfortunately, the only architecture that will appear for those teams is a big ball of mud. (Or, if you’re hungry, a big ball of spaghetti.)
Pitfall #2 – Not following the data
An excellent principle for designing a software architecture is to follow the data. My first modern embedded software principle is that data dictates design. Data is the real asset that every embedded system is designed to manage. Data comes into a system in various forms to create inputs. Those data inputs are then processed, stored, and/or used to produce outputs from the system.
When you design embedded software, you shouldn’t care what temperature sensor is used, what push button was designed into the system, or even what microcontroller is used. Instead, designers and developers should identify and follow the data assets in their system. So, for example, the architecture should identify the temperature data asset instead of worrying about the temperature sensor vendor. Likewise, in the software architecture, we don’t care about the hardware, just that there is an interface that will serve as the temperature data.
If you follow the data, the software architecture necessary to perform the desired system behaviors on that data will naturally fall into place. Strangely enough, it will create a hardware-independent and more easily tested software architecture. Avoid this pitfall by identifying and following the data through the software system.
Pitfall #3 – Failing to consider response times
Embedded systems often have real-time response requirements associated with them. For example, if a user presses an emergency stop button, the system shall halt within ten milliseconds. Occasionally, I’ve seen software architects get overly excited about creating an elegant, all-encompassing software architecture or attempt to adopt a more modern architecture that destroys real-time performance.
While aiming to create scalable and flexible architecture, software architects also need to consider the implementation impacts of their architectural decisions. At the architect stage, it may not be able to quantify the response times fully. However, high risk areas can be identified and tested as soon as possible.
I often see developers struggle with when creating a task-based architecture. If the architect is less experienced with task-based design patterns, it’s not uncommon to have far more latency in response than expected. Many timing problems stem from interactions between interrupts and periodic tasks. The issue can sometimes be resolved by changing the problem task’s architecture from time-based to event-driven.
Pitfall #4 – No implementation / architecture feedback loop
When a team puts together its software architecture, I often see teams act like the architecture is gospel and can’t be changed. It’s not uncommon for the developers writing the code to make architectural changes and never feed those changes back to the architects. The pitfall is that there needs to be a feedback loop between the implementation and the architecture.
The architects build their architecture based on what they perceive to be the optimal solution for the application. Unfortunately, the architects often don’t have all the information they need to build the architecture fully. Therefore, it’s up to the coders during implementation to update the architects on their findings, issues, and so forth to determine the best direction for the overall software architecture. If the coders make the changes themselves without feedback from the architects, they may move the system in a direction that is not optimal for the architecture. The result is that the code and the architecture slowly accumulate technical debt that gets in the way of success.
Pitfall #5 – Picking the wrong architecture
Several different types of software architectures can be applied to embedded applications. For example, there are unstructured monoliths, layered monoliths, event-driven, state-driven, and microservice architectures. If an architect chooses the wrong architecture for their system, they may discover that they have issues with scaling the application, issues with response times, or many other potential problems.
Several reasons a developer may select the wrong architecture for the job. First, they may just be interested in trying a new architecture they have never used before. While broadening one’s horizons can be good, designers must be careful to ensure that the architectural type they decide to use solves the problems at hand and doesn’t introduce complexity or other potential issues. For example, microservice architectures have become quite popular, but they can suffer from complexity and response time issues if one is not careful.
When architecting an embedded system, carefully look at the data and the domains in which that data operates to help identify the architectural model that will work best for the application. In some applications, you may discover that mixing architectural types is required to solve the problem.
Software architecture is a critical design element that guides developers in building an embedded application successfully. Developers can leverage a wide range of software architectures and design patterns to solve common design problems. Before exploring those architectures and design patterns, we’ve first examined five software architecture pitfalls that can get in the way of good architecture.
What additional pitfalls have you seen teams fall into when developing their embedded software architectures?
[1] https://en.wikipedia.org/wiki/IEEE_1471 . IEEE 1471 has been superseded by IEEE 42010. (I just like the IEEE 1471 definition).
For more Embedded, subscribe to Embedded’s weekly email newsletter.
I’m also a big fan of event-driven architecture. But there is a lot of confusion about the subject and many developers believe that event-driven is only for GUIs. In your future post, could you explain what “event-driven” means and how it differs from traditional sequential programming based on blocking (or polling)?
You must Sign in or Register to post a comment.
This site uses Akismet to reduce spam. Learn how your comment data is processed.