Location>code7788 >text

The main design mode used in DAB implementation

Popularity:584 ℃/2025-02-01 09:16:24

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

  • passonTopic()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

  1. Log adapter: Convert the system log interface to DAB standard log interface
  2. 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.
    class topichandler {
         public:
         static void int (int MaxthReads); // explicit initialization
         static void destroy (); // Express resource release
         Static void registerhandler (/*...*/);
         Topichandler () = delete; // Forbidden instantiation
         };
    Design consideration
    1. Life cycle controlled:passinit()/destroy()Clarify management resources
    2. Test friendly: Support independent initialization of different test cases
    3. Avoid global state: Each module maintains its static data
    4. Compilation period constraint= deleteProhibit illegal operation
      Compare traditional single example
    • The only example of not forced global
    • Undefeated initialization sequence problem
    • Support multi -environment configuration (test/production)

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 passregisterHandlerRegister closure
Bridge Business processing and MQTT communication decoupling setPublishFuncImplement protocol isolation
Strategy mode Test and production environment configuration switch DABPropertiesDynamic 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

  1. Topic standardization: Automatically add device ID prefix
  2. Response isolation: Generate a special response Topic channel
  3. Abnormal protection: Built -in air pointer inspection and other security mechanisms
  4. 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
 }