Boundaries & Boundary Anatomy
- **Key Concepts & Challenges**
- **Code Examples with Tests**
- **Example 1: Interface-Based Boundary (C++)**
- **Example 2: Dependency Inversion (C)**
- **Example 3: Plugin Architecture (C++)**
- **Critical Analysis**
- **Common Pitfalls**
- **Multiple-Choice Questions**
- **Answers & Explanations**
- **Test Code**
Key Concepts & Challenges
-
Boundary Definition
- Purpose: Isolate components to manage change and reduce coupling.
- Mechanisms: Use interfaces, dependency inversion, or abstract classes to decouple high-level policies from low-level details.
-
Dependency Direction
- Rule: Dependencies should point toward stable abstractions (e.g., interfaces) to invert control.
-
Plugin Architecture
- Goal: Allow dynamic extension by isolating core logic from plugins.
Code Examples with Tests
Example 1: Interface-Based Boundary (C++)
Scenario: Separate data processing from I/O operations.
Boundary: Define an IWriter
interface to abstract output mechanisms.
// File: iwriter.h
#pragma once
#include <string>class IWriter {
public:virtual ~IWriter() = default;virtual void write(const std::string& data) = 0;
};// File: console_writer.h
#include "iwriter.h"
class ConsoleWriter : public IWriter {
public:void write(const std::string& data) override {std::cout << "[CONSOLE] " << data << std::endl;}
};// File: data_processor.cpp
#include "iwriter.h"
class DataProcessor {IWriter* writer;
public:DataProcessor(IWriter* w) : writer(w) {}void process() {writer->write("Processing complete.");}
};// Test in main.cpp
#include "console_writer.h"
int main() {ConsoleWriter cw;DataProcessor dp(&cw);dp.process(); // Output: [CONSOLE] Processing complete.return 0;
}
Compilation:
g++ -std=c++17 main.cpp console_writer.cpp data_processor.cpp -o app && ./app
Example 2: Dependency Inversion ©
Scenario: Decouple a Logger
from its output method.
Boundary: Use function pointers to invert dependencies.
// File: logger.h
#pragma once
typedef void (