Chapter 13
Architecture, Performance, Safety, and Security
Bachelor Program in Mechatronics Engineering
Object-Oriented Programming with C++
•
Bachelor
Architecture, Performance, Safety, and Security
Introduction
Object-oriented C++ is used in mechatronic systems ranging from motor controllers and robotic manipulators to industrial inspection equipment. In such systems, successful software is not defined only by whether it produces the correct output. It must also be understandable, responsive, memory-efficient, dependable, secure, testable, and maintainable over many years.
These qualities are strongly influenced by architecture and engineering discipline. Architecture determines how responsibilities are divided. Performance engineering determines whether timing and resource constraints are satisfied. Safety engineering reduces the probability and consequences of hazardous behavior, while security engineering protects the system from unauthorized or malicious actions. Coding standards, traceability, risk analysis, and maintainability metrics provide evidence that these properties have been considered systematically.
This chapter compares four common architectures—layered, component-based, event-driven, and plugin-based—and connects architectural decisions with measurement, C++ implementation, functional safety, cybersecurity, and professional governance.
Learning Objectives
After studying this chapter, you should be able to:
Compare layered, component-based, event-driven, and plugin architectures.
Select an architecture appropriate to a mechatronic application.
Measure execution time, latency, throughput, memory use, and allocation behavior.
Apply C++ coding standards and resource-management principles.
Explain secure coding and functional-safety practices.
Perform basic risk analysis and maintain bidirectional requirements traceability.
Interpret maintainability metrics and identify their limitations.
Evaluate architectural and engineering trade-offs in a realistic case.
1. Software Architecture as an Engineering Decision
Software architecture is the set of major structures, responsibilities, interfaces, and constraints that organize a software system. It is not merely a collection of classes. A class diagram describes local relationships; an architecture also describes deployment, communication, timing, ownership, failure handling, and dependencies.
A mechatronic controller commonly contains sensing, estimation, control, actuation, communication, diagnostics, and human-machine-interface functions. Architecture should make these responsibilities explicit and should prevent changes in one area from unpredictably damaging another.
Important architectural quality attributes include:
Functional suitability: the system performs required functions.
Timing performance: deadlines and response-time requirements are satisfied.
Reliability: failures are infrequent and handled predictably.
Safety: hazards are controlled so that risk is tolerable.
Security: confidentiality, integrity, availability, and authenticity are protected.
Maintainability: changes, tests, and fault diagnosis are practical.
Portability: software can be moved to another processor, operating system, or platform.
Architectural quality attributes often conflict. Dynamic plugin loading may improve extensibility but increase attack surface. Abstraction may improve maintainability but introduce execution overhead. A disciplined design makes these trade-offs explicit rather than accidental.
2. Four Architectural Styles
2.1 Layered architecture
A layered architecture groups software by abstraction level. A typical embedded system may contain:
Hardware and device drivers.
Hardware-abstraction and operating-system services.
Domain services such as filtering, kinematics, and control.
Application coordination and user interfaces.
A higher layer normally uses services of a lower layer, while lower layers do not depend on application details. For example, a trajectory planner should request sensor data through an interface rather than directly manipulating hardware registers.
Advantages include conceptual clarity, replaceability of lower-level implementations, and easier teaching and testing. Limitations include performance overhead from excessive indirection and the temptation to bypass layers when deadlines are tight. Strict layers can also become difficult when a function naturally spans several concerns, such as time synchronization or safety monitoring.
2.2 Component-based architecture
A component is a cohesive unit with explicit provided and required interfaces. A component may be a C++ library, a process, a hardware abstraction, or a deployable service. Components communicate through contracts rather than through access to one another's internal data.
Component-based design supports independent development and substitution. A simulated motor component can replace a physical motor interface during testing. Good components have high cohesion, low coupling, explicit ownership, and stable interfaces.
The main risks are interface complexity, version incompatibility, hidden shared state, and communication overhead. In real-time systems, the cost and scheduling behavior of component communication must be measured rather than assumed.
2.3 Event-driven architecture
In an event-driven system, events cause handlers or subscribers to execute. An event can represent a sensor update, timer expiration, communication packet, fault, or user command. An event dispatcher may use a queue, interrupt service routine, message broker, or operating-system mechanism.
Event-driven designs are effective when inputs are asynchronous and when independent activities should not be tightly coupled. They can improve responsiveness and make extensions easier. However, event ordering, queue overflow, priority inversion, reentrancy, and fault propagation require careful treatment. A control loop with a fixed sampling period should not be replaced by an uncontrolled event chain merely because events appear convenient.
2.4 Plugin architecture
A plugin architecture allows functionality to be loaded or registered separately from the core program. Examples include robot end-effectors, machine-vision algorithms, simulation models, and vendor-specific communication drivers.
Plugins provide extensibility and can allow third parties to add capabilities without rebuilding the core. They also create significant governance concerns: binary compatibility, versioning, permissions, initialization failure, dependency management, and untrusted code. In safety-critical or security-sensitive systems, plugins should be signed, validated, isolated where possible, and excluded from safety functions unless their assurance can be demonstrated.
Style
Main strength
Main concern
Suitable example
Layered
Clear abstraction and separation
Cross-layer workarounds and overhead
Embedded controller software
Component-based
Replaceable, testable units
Interface and version complexity
Sensor or actuator modules
Event-driven
Responsive asynchronous behavior
Ordering and concurrency faults
Alarm and communication handling
Plugin
Extensibility
Security and compatibility risk
Optional analysis algorithms
Comparison of layered, component-based, event-driven, and plugin architecture concepts
Figure: Comparison of layered, component-based, event-driven, and plugin architecture concepts
Figure: Conceptual comparison of four architectural styles.
3. Performance and Memory Engineering
Performance must be measured against a stated workload and acceptance criterion. “Fast” is not a sufficient requirement. A control task might require a worst-case execution time below 500 μs, while a diagnostic report might be acceptable within 200 ms.
3.1 Core performance measures
Execution time: time taken by one operation or task.
Latency: delay between an input or request and its observable response.
Throughput: completed work per unit time.
Jitter: variation in timing from one execution to another.
Utilization: fraction of a resource's capacity being used.
Peak memory: maximum memory occupied during a workload.
Allocation rate: amount or number of dynamic allocations over time.
For repeated measurements, the arithmetic mean is:
\bar{t} = (1/n) ∑ᵢ₌₁ⁿ tᵢ
Here, ti is the i-th measured time in seconds, n is the number of observations, and \bar{t} is the mean time. The mean is useful for typical behavior but can hide rare deadline violations. Percentiles, maximum observed time, and worst-case analysis are therefore important in control software.
If an operation processes N items in total time T, its average throughput is:
R = N/T
R is measured in items per second when N is an item count and T is in seconds. This formula describes observed average throughput; it does not prove a worst-case guarantee.
A processor utilization estimate for periodic tasks is:
U = ∑ᵢ₌₁ⁿ Cᵢ/Pᵢ
Ci is the execution time of task i and Pi is its period, both in the same time unit. The expression estimates workload utilization under stated scheduling assumptions. It does not by itself prove schedulability, especially when blocking, interrupts, context switches, deadlines, and nonpreemptive sections are present.
3.2 Measurement practice
Use a representative workload, release build, controlled hardware, and repeatable input. Measure boundaries with a monotonic clock; wall-clock time can jump because of clock synchronization. Separate warm-up effects from steady-state behavior. Record compiler version, optimization options, processor, operating system, input size, and measurement method.
C++ tools include profilers, sanitizers, hardware performance counters, heap profilers, static analyzers, and benchmark frameworks. A benchmark should prevent the compiler from eliminating the operation being measured and should distinguish setup cost from the operation itself.
3.3 Memory and resource management
Modern C++ favors RAII: acquisition is tied to object lifetime, and cleanup occurs automatically in destructors. Prefer std::vector, std::array, std::string, smart pointers, and standard algorithms over raw ownership. std::unique_ptr expresses exclusive ownership; std::shared_ptr expresses shared ownership but incurs reference-counting and lifetime complexity. Avoid shared_ptr by default.
Dynamic allocation can produce fragmentation, unpredictable latency, and failure under memory pressure. Real-time code may use preallocated buffers, object pools, bounded queues, and fixed-capacity containers. Ownership should be explicit, and allocation failure should have a defined response.
The terms represent code, static data, stack, dynamically allocated objects, and communication or I/O buffers. This is an engineering accounting model, not a universal hardware equation; some systems share or compress regions. Peak rather than average values are usually relevant for capacity decisions.
4. Coding Standards and Maintainable C++
A coding standard converts quality expectations into reviewable rules. Organizations may adopt guidelines such as the C++ Core Guidelines, CERT C++ recommendations, or project-specific rules. A standard should address naming, formatting, interfaces, error handling, ownership, concurrency, exceptions, casts, initialization, and permitted language features.
High-value practices include:
Initialize objects and use strong types for units and states.
Keep functions small and cohesive, but do not split code mechanically.
Prefer const, constexpr, scoped enumerations, and narrow interfaces.
Avoid macros when constants, templates, or functions are safer.
Minimize global mutable state and hidden dependencies.
Use compiler warnings at a strict level and treat important warnings as defects.
Document preconditions, postconditions, ownership, thread-safety, and timing assumptions.
Review interfaces for invalid states and impossible combinations.
Maintainability metrics can support engineering judgment. Cyclomatic complexity is commonly approximated by:
V(G) = E − N + 2P
Here, E is the number of control-flow edges, N is the number of nodes, and P is the number of connected components; for one connected routine, P = 1. Higher values indicate more independent control-flow paths and often greater testing difficulty. The metric is not a direct measure of defects or design quality. Coupling, cohesion, duplication, change frequency, defect history, and test coverage should also be examined.
5. Secure C++ Development
Security protects the system against intentional misuse as well as accidental exposure. A secure design begins with threat modeling: identify assets, trust boundaries, entry points, attackers, consequences, and mitigations.
Common C++ weaknesses include buffer overflows, use-after-free, double deletion, integer overflow, unchecked input, format-string errors, unsafe deserialization, command injection, and inadequate authentication. RAII and standard containers reduce but do not eliminate these risks.
Secure practices include validating length, range, type, and encoding; using bounds-checked interfaces where appropriate; avoiding unsafe casts; authenticating software updates; protecting keys; minimizing privileges; and failing closed for security decisions. A plugin should not receive filesystem, network, or actuator authority unless required. Dependencies must be inventoried and updated through controlled processes.
Security and safety are related but distinct. A safety fault may result from a failed sensor; a security incident may deliberately manipulate that sensor. Both can produce hazardous motion, so hazard analysis and threat modeling should exchange information.
6. Functional Safety and Risk Analysis
Functional safety concerns the ability of a system to respond safely when faults occur. It does not mean that every failure is impossible. It means that hazards are identified, risk is assessed, and protective measures are designed and verified. Relevant standards depend on the sector, such as IEC 61508, ISO 13849, IEC 62061, or ISO 26262.
A basic risk model is:
Risk = Probability × Severity
Probability represents the likelihood of a hazardous event under defined assumptions, and severity represents the consequence. Some methods also include exposure and possibility of avoidance. Risk matrices are ordinal decision aids, not precise probabilities, and must not be interpreted as exact physical laws.
A practical hazard analysis asks:
What hazardous condition can occur?
What initiating faults or misuse could produce it?
Who or what can be harmed?
What independent protective measures exist?
How is the safety function tested and diagnosed?
What evidence demonstrates that the residual risk is acceptable?
Software safety practices include deterministic state machines, defensive range checks, watchdogs, plausibility checks, safe outputs, redundant or diverse sensing where justified, fault logging, and independence between protection and ordinary control functions. A software emergency stop should not be the only protection when a hardwired or energy-isolating measure is required by the hazard analysis.
7. Requirements Traceability and Verification
Traceability links stakeholder needs to system requirements, architecture, design elements, implementation, tests, anomalies, and release evidence. Bidirectional traceability answers both questions: “Which requirement does this code and test satisfy?” and “Where is this requirement implemented and verified?”
A traceability record may contain an identifier, requirement text, safety or security classification, design element, source files, verification method, test result, reviewer, and change history. Requirements should be testable and should include measurable timing, accuracy, operating conditions, and failure behavior where relevant.
Verification asks whether the product was built correctly; validation asks whether the correct product was built for its intended use. Unit tests, static analysis, integration tests, hardware-in-the-loop tests, fault injection, stress tests, code review, and acceptance tests provide complementary evidence. Passing tests does not prove absence of defects, particularly when requirements are incomplete or test conditions are narrow.
8. An Illustrative Case: Robotic Pick-and-Place Cell
Background
Consider an illustrative robotic cell that identifies components with a camera, plans a pick location, commands a six-axis robot, and reports production data. The cell must stop safely when a guard opens or when a person enters a protected area.
Problem
The first prototype uses a single application loop. Camera processing, motion control, networking, logging, and safety checks share mutable global objects. Operators report unpredictable delays, and a third-party vision library requires dynamic loading.
Analysis
The architecture has poor separation and makes timing difficult to measure. Camera processing can delay motion commands, while logging can allocate memory during operation. The plugin is a security boundary because it is externally supplied. Safety checks are not sufficiently independent from ordinary application code.
Approach
The redesigned system uses layers: hardware drivers, real-time services, control services, and application coordination. Sensor, planner, actuator, and diagnostics are explicit components. Camera frames generate events to a bounded processing queue, while the control loop remains periodic. The vision algorithm is a plugin behind a narrow interface and is loaded only after signature and compatibility checks. It runs with restricted permissions and cannot directly command actuators.
The safety subsystem independently monitors guard switches, speed limits, communication health, and actuator feedback. On a detected hazard, it commands a defined safe state. Requirements are assigned identifiers and traced to design elements and tests. Performance tests record mean, high-percentile, maximum observed execution time, queue occupancy, and peak memory. Static analysis, sanitizers in testing, code review, fault injection, and hardware-in-the-loop tests are added to the verification plan.
Outcome
The redesign does not guarantee perfect software, but it makes responsibilities, timing assumptions, trust boundaries, and evidence visible. Performance bottlenecks can be localized, plugins can be replaced, and safety functions can be assessed independently. The principal improvement is not a particular C++ feature; it is the disciplined relationship among architecture, measurement, risk control, and traceability.
Learning points
A periodic control task should not depend on unbounded event-processing work.
Extensibility must be balanced with plugin trust and isolation.
Safety monitoring requires explicit failure behavior and evidence.
Metrics are useful only when tied to requirements and representative workloads.
Architectural simplicity is often a safety and security advantage.
9. Contemporary Developments and Professional Practice
Modern C++ standards improve expressiveness through concepts, ranges, safer library facilities, and improved compile-time computation, but newer language features do not automatically satisfy real-time or safety requirements. Artificial intelligence may be used for vision, prediction, or anomaly detection; however, learned components introduce dataset shift, uncertain confidence, difficult explainability, and challenging validation. They should be bounded by conventional safety mechanisms and monitored for out-of-distribution behavior.
Industry increasingly combines static analysis, continuous integration, software bills of materials, vulnerability scanning, reproducible builds, signed artifacts, and runtime observability. These practices support both security and maintainability. Governance should define who approves exceptions, how vulnerabilities are reported, how long dependencies are supported, and how field updates are authenticated and recovered.
Challenges and Limitations
No architecture eliminates complexity. Layering can add latency, events can create nondeterministic interactions, components can produce interface failures, and plugins can expand attack surfaces. Performance measurements are environment-dependent and may omit rare worst cases. Metrics such as complexity and coverage can be gamed and should not replace engineering judgment. Risk matrices simplify uncertainty, while standards provide process guidance rather than automatic correctness. Safe and secure systems require technical evidence, competent review, operational discipline, and continuous improvement.
Chapter Summary
Architecture organizes responsibilities and determines how qualities such as performance, safety, security, and maintainability can be achieved. Layered architecture emphasizes abstraction, component-based architecture emphasizes replaceable contracts, event-driven architecture handles asynchronous activity, and plugin architecture emphasizes extensibility. Each has benefits and risks.
Performance engineering requires explicit requirements, representative workloads, controlled measurement, and attention to worst-case behavior. Execution time, latency, throughput, utilization, jitter, peak memory, and allocation behavior should be interpreted in context. RAII, standard containers, explicit ownership, bounded resources, and strict coding standards improve C++ reliability.
Secure coding addresses input validation, memory safety, authentication, least privilege, dependency control, and trust boundaries. Functional safety identifies hazards, reduces risk, defines safe failure behavior, and produces verification evidence. Traceability links requirements to design, implementation, tests, and changes. Maintainability metrics such as cyclomatic complexity are useful indicators but not complete quality measures. Professional mechatronics software results from integrating architecture, measurement, coding discipline, safety, security, and evidence-based governance.
Key Terms
Architecture: The major structures, interfaces, responsibilities, and constraints of a system.
Layered architecture: An organization in which higher abstraction layers use lower-layer services.
Component: A cohesive unit with explicit provided and required interfaces.
Event-driven architecture: A style in which events trigger handlers or subscribers.
Plugin: Separately developed functionality loaded or registered through a host interface.
Latency: Delay between an input or request and the corresponding response.
Throughput: Amount of completed work per unit time.
Jitter: Variation in timing across executions.
RAII: C++ resource-management technique connecting resource lifetime to object lifetime.
Peak memory: Maximum memory occupied during a defined workload.
Cyclomatic complexity: A control-flow measure related to independent execution paths.
Threat modeling: Systematic identification of assets, threats, trust boundaries, and mitigations.
Functional safety: Reduction of unacceptable risk arising from hazardous system behavior.
Hazard: A potential source of harm.
Risk: Combination of likelihood and consequence under stated assumptions.
Traceability: Ability to relate requirements, design, implementation, tests, and changes.
Verification: Evidence that the product was built according to specified requirements.
Validation: Evidence that the product meets its intended purpose and user needs.
Least privilege: Giving an entity only the authority required for its task.
Worst-case execution time: The greatest execution time considered under defined conditions.
Review Questions
Short Answer Questions
What is the principal purpose of a software architecture?
State one advantage and one limitation of event-driven architecture.
Why is peak memory often more important than average memory in embedded systems?
Distinguish verification from validation.
What does RAII achieve in C++?
Long Answer Questions
Compare layered, component-based, event-driven, and plugin architectures for a robotic system.
Explain how performance measurements should be designed for a periodic motor-control task.
Discuss how secure coding practices reduce risks in C++ mechatronic software.
Describe a functional-safety workflow from hazard identification to verification evidence.
Explain the benefits and limitations of requirements traceability and maintainability metrics.
Analytical / Application Questions
A periodic task executes for 2 ms every 10 ms, while a second task executes for 3 ms every 20 ms. Calculate the workload utilization using U = ∑ Ci/Pi, and discuss why the result alone does not prove schedulability.
Design an architecture for a robot that must process asynchronous alarms while maintaining a fixed-period control loop. Justify the placement of layers, components, queues, and safety functions.
A plugin can access camera data, the network, and actuator commands. Identify the principal security and safety risks and propose interface, permission, validation, and testing controls.
Multiple Choice Questions with Answers
Question 1
Which architecture most directly organizes software by levels of abstraction?
A. Layered architecture
B. Event-driven architecture
C. Plugin architecture
D. Peer-to-peer architecture
Correct Answer: A. Layered architecture
Question 2
What does R = N/T represent when N is completed work and T is elapsed time?
A. Latency
B. Throughput
C. Memory utilization
D. Cyclomatic complexity
Correct Answer: B. Throughput
Question 3
Which C++ technique ties resource cleanup to object lifetime?
A. Macro expansion
B. RAII
C. Global mutable state
D. Unchecked casting
Correct Answer: B. RAII
Question 4
Why can maximum observed execution time be important in a control system?
A. It determines source-code size
B. It reveals possible deadline violations
C. It eliminates the need for testing
D. It measures software security directly
Correct Answer: B. It reveals possible deadline violations
Question 5
Which practice best limits the damage caused by a compromised plugin?
A. Giving it unrestricted actuator access
B. Disabling interface validation
C. Applying least privilege and isolation
D. Loading it before authentication
Correct Answer: C. Applying least privilege and isolation
Question 6
For one connected control-flow graph, cyclomatic complexity is commonly represented as which expression?
A. E + N + 2
B. E − N + 2
C. N − E − 2
D. E × N
Correct Answer: B. E − N + 2
Question 7
What is the purpose of bidirectional requirements traceability?
A. To replace all integration tests
B. To link requirements both to implementation and to verification evidence
C. To guarantee zero defects
D. To maximize dynamic allocation
Correct Answer: B. To link requirements both to implementation and to verification evidence
Question 8
Which statement correctly distinguishes validation from verification?
A. Validation asks whether the correct product was built; verification asks whether it was built correctly
B. Validation concerns only memory; verification concerns only security
C. They are identical terms
D. Verification occurs only after product release
Correct Answer: A. Validation asks whether the correct product was built; verification asks whether it was built correctly
Question 9
A task uses 2 ms every 10 ms and another uses 3 ms every 20 ms. What is their estimated utilization?
A. 0.15
B. 0.25
C. 0.35
D. 0.50
Correct Answer: C. 0.35
Question 10
Which statement about risk matrices is most accurate?
A. They are exact physical laws
B. They eliminate the need for hazard analysis
C. They are decision aids whose scales and assumptions must be defined
D. They measure execution time directly
Correct Answer: C. They are decision aids whose scales and assumptions must be defined
Object-Oriented Programming with C++
Chapter 13
of 14