DAB C ++ version design mode application practice
1. command mode (Command Pattern)
Design goal
- Module decouple: Realize independent compilation, testing, and running of each module, and to eliminate direct dependence between modules
- Extended preparation: Lay the foundation for the implementation of the bridge mode
- Dependence inverted: Through the command object reversing the module depends on the direction
- Coupled reduction: Coupling the module into the command object coupling
1.1 MQTT module implementation
#Pragma once
#include <string>
#include <vector>
#include <functional>
/**
* @Class HIMQTTClient
* @Brief MQTT client core class, provide functions such as connection management, message release subscription
*
* @Note adopts the command mode to implement the message processing mechanism
*/
class himqttclient {
public:
// Connect the management interface
Static Void Start (Const Char* ip, int Port, Const Char* User,
const char* password, const char* clientid);
static void stop ();
// Message management interface
Static void subscriprbe (const std :: vector <std :: String> & Topics);
Static Bool Publish (Const Char* Topic, Const Char* Body);
// Command mode callback settings
Static void ONTOPIC (Const STD :: FUNCTION <Void (Const Char*, Const Char*,
const char*, const char*)> & func);
};
Design highlight:
- pass
onTopic()
Set the command object to implement message processing - Support module independent unit test
- Eliminate the circular dependence with other business modules
1.2 Topic processor implementation
#Pragma once
#include <map>
#include <functional>
#include "context/dab_context.h"
/**
* @Class Topichandler
* @Brief Theme processor based on command mode
*
* @Note User registration mechanism instead of traditional Switch-Case branch processing
*/
class topichandler {
public:
// Life cycle management
Static Void Init (int Maxthreads);
static void destroy ();
// Command registration interface
Static Void Registerhandler (Const STD :: MAP <std :: String,
STD :: FUNCTION <Void (DabContext &) >> & Handles);
// Unified message entrance
Static Void Ontopic (Const Char* Topic, Const Char* Body,
const char* response_topic, const char* correlation_data);
};
Innovation point:
- Dynamic registration mechanism to achieve processing logic can be configured
- Unified message entrance simplifies the call link
- Naturally support multi -thread processing
1.3 Context object design
#Pragma once
#include "context/dab_status.h"
#include "context/dab_request.h"
#include "context/dab_response.h"
/**
* @class dabcontext
* @Brief request to handle the context object
*
* @Note uses command mode package message release function
*/
class dabcontext {
public:
// Status management interface
book is_ok () const;
void success ();
void ClientFail (Const Char* OUT_LOG, Const Char* Inner_log = Nullptr);
// Message to publish command interface
Static void Setpublishfunc (Const STD :: FUNCTION <Void (Const Char*, Const Char*)> & Func);
Static Void Publish (DabContext & Context);
// Data member
Dabstatus status;
DabRequest Request;
Dabresponse response;
};
Technical advantage:
- Hidden MQTT implementation details
- Support multiple message release strategies
- The context contains the design simplified unit test
1.4 log module implementation
#Pragma once
#include <functional>
/**
* @enum dabloglevel
* @Brief log level enumeration definition
*/
enum class dabloglevel {info, warning, error, fatal, alway,
namespace dab {
/**
* @Brief log back adjustment settings interface
* @param callback log processing function prototype:
* VOID (log level, file name, function name, line number, log content)
*/
void set_log_callback (std :: FUNCTION <VOID (DABLOGLEVEL, Const Char*,
const char*, int, const char*)> callback);
// Log macro definition
#Define dablog_info (...) dab :: wrbloglevel :: info, __file__, __function___, __line___, __va_args__)
#Define Dab_assert (Expr, DESC) \
do {if (! (Expr)) {\
dab :: ON_ASSERT_FAIL (__ File__, __Function__, __LINE__); \
}} While (0)
}
Core value:
- Flexible adaptation of different log implementations
- Support runtime log strategy switch
- Provide rich debugging information
2. Bridge pattern (Bridge Pattern)
Design goal
- Architecture: Separation abstraction and specific implementation
- Independent evolution: Each module can change independently
- Unified interface: Provide standardized service capabilities
System bridge implementation
Void Publish (Const Char* Topic, Const Char* Body) {
Himqttclient :: publish (topic, body);
}
extern "c" int RundabService () {) {)
// Initialize each module
Topichandler :: Init (dabproperties :: max_handle_threads);
Dabhandler :: init ();
// Bridge key points
Himqttclient :: Ontopic (Topichandler :: Ontopic);
DabContext :: Setpublishfunc (publish);
// Subscription and registration
Himqttclient :: Subscribe (dabhandler :: gettopics ());
Topichandler :: registerhandler (dabhandler :: gettopichandles ());
// Start the service
Himqttclient :: Start (dabproperties :: mqtt_ip.c_str (),,,
Dabproperties :: mqtt_port, ...);
Return 0;
}
Bridge advantage:
- Decodic business logic and communication protocol
- Module communicates through abstract interface communication
- New agreement supports minimum costs
3. Adapter mode (adapter pattern)
Design goal
- Interface standardization: Uniform interface specifications of different systems
- Dependence inverted: Reverse system interface dependency direction
- Extended support: Lay the foundation for the implementation of the strategy model
Typical application
- Log adapter: Convert the system log interface to DAB standard log interface
- Service adaptation: The feature interface of the packaging platform is a unified service interface
Adaptive income:
- Business code does not depend on specific implementation
- New platform support only needs to implement the adapter
- Maintain core logic stability
4. Strategy Pattern
Application scenarios
Scene | Implementation strategy | Superiority |
---|---|---|
Television environment | Real hardware interface implementation | Full Functional Support |
Cloud environment | Mock interface implementation | Automation of hardware -free dependencies |
Unit test | Memory lightweight implementation | Quick test execution |
Strategic configuration
// Test environment initialization example
void dabinit () {
DabContext :: setpublic
Dablog_alware ("Test Publish: %S-> %S", T, B);
});
Topichandler :: registerhandler ({
{"test/topic1", [] (dabContext & ctx) {/ * mock processing logic */}},
{"test/topic2", [] (dabContext & ctx) {/ * mock processing logic */}}
});
}
Strategic advantage:
- Dynamic switching implementation during runtime
- Environmental isolation guarantee test reliability
- Supporting a variety of deployment plans parallel
5. Single mode
In the implementation of DAB, the singles mode intentionally avoided the use of a static class.
Design consideration:class topichandler { public: static void int (int MaxthReads); // explicit initialization static void destroy (); // Express resource release Static void registerhandler (/*...*/); Topichandler () = delete; // Forbidden instantiation };
-
Life cycle controlled:pass
init()
/destroy()
Clarify management resources - Test friendly: Support independent initialization of different test cases
- Avoid global state: Each module maintains its static data
-
Compilation period constraint:
= delete
Prohibit illegal operation
Compare traditional single example:
- The only example of not forced global
- Undefeated initialization sequence problem
- Support multi -environment configuration (test/production)
-
Life cycle controlled:pass
6. Test system design
1. Test environment construction
#include <gtest/>
#include "dab/dab_api.h"
// Global test environment category
Class TESTV: Public testing :: environment {
public:
void setup () override {dabinit ();} // test case initialization
void teardown () override {dabdestory ();} // Test resource recovery
};
// Core initialization logic
namespace {
// The simulation message release function
Void Publish (Const Char* Topic, Const Char* Body) {
Dablog_alware ("[test] topic:%s \ npayload:%s", topic, body);
}
void dabinit () {
Dabproperties :: device_id = "test_device"; // Set test device ID
Topichandler :: init (5); // Initialize message processing thread pool
Dabhandler :: init (); // The initialization of the business processor
DabContext :: Setpublishfunc (publish); // Inject an analog posterior
// Register the topic processing function
Topichandler :: registerhandler (dabhandler :: gettopichandles ());
}
void dabdestory () {
Topichandler :: Destroy (); // Clean the message processor
Dabhandler :: Destroy (); // Clean up the business processor
}
}
// Test the main entrance
int Main (int argc, char ** argv) {
testing :: InitgoogleTest (& Argc, ARGV);
testing :: addglobaltenvalonment (New Testenv);
RETURN RUN_ALL_TESTS ();
}
2. Design mode application analysis
Design pattern | Application scenarios | Implementation points |
---|---|---|
Command mode | Message processing function registration | passregisterHandler Register closure |
Bridge | Business processing and MQTT communication decoupling |
setPublishFunc Implement protocol isolation |
Strategy mode | Test and production environment configuration switch |
DABProperties Dynamic configuration |
3. Test auxiliary tool implementation
1. Topic processing tool class
namespace {
// Generate standard Topic format
STD :: String Formattopic (Const STD :: String & Basetopic) {
STD :: OSTRINGSTREAM OSS;
OSS << "dab/" << dabproperties :: device_id <</"<< Basetopic;
Return ();
}
}
// Uniform test entry function
void ONTOPICTEST (Const STD :: String & Topic, Const STD :: String & Request) {
Topichandler :: ONTOPIC (
Formattopic (topic) .c_str (), // Format the request topic
request.c_str (), // Test request load
"_Response/" + formttopic (topic) .c_str (), // response topic
"// Related data
);
}
2. Tool design highlights
- Topic standardization: Automatically add device ID prefix
- Response isolation: Generate a special response Topic channel
- Abnormal protection: Built -in air pointer inspection and other security mechanisms
- Logic: Automatically record test message flowing
4. Application function test case
1. Application management test set
Test (Dabhandler, ApplicationManagement) {{
// Basic function test
OntopicTest ("Applications/List", "{}"); // Veritage query
// Typical scene test
ONTOPICTEST ("Applications/Launch",
R "({" appid ":" youtube "})); // Standard application startup
// Bring parameter start test
ONTOPICTEST ("Applications/Launch",
R "({{
"Appid": "Netflix",
"Parameters": [[
"-Key",,
"https%3A%2F %% 2F",
"-Standalone_param"
]
}) ")))
// Status management test
ONTOPICTEST ("Applications/Get-State",
R "({" appid ":" Youtube "});
// Exit mechanism Test
ONTOPICTEST ("Applications/EXIT",
R "({" appid ":" youtube "})"); // Routine exit
ONTOPICTEST ("Applications/EXIT",
R "({" appid ":" youtube "," background ": true})); // exit in the background
}