Advanced Embedded Programming Techniques: Data-Driven Programming

Advanced Embedded Programming Techniques: Data-Driven Programming

1. Introduction

Today, I would like to recommend a piece of pure instrumental music that has truly touched the author; it might just be one of those few pieces.

Alright, today I will introduce the technique of data-driven programming, which can help everyone write high-quality code in their daily work.

Advanced Embedded Programming Techniques: Data-Driven Programming

2. What is Data-Driven Programming?

The author has always believed that “code without design philosophy has no soul”, so in many years of program design, I generally design the program architecture first and then proceed to coding. Previously, I introduced the concept of <【Killer Technique】 using “Universal C Programming” to lead into “Object-Oriented Programming”>, which should have benefited many newcomers who had not been exposed to this content before. I hope to bring more similar articles, which led to this new work.

1. Let’s look at data-driven programming through the example of an MP3 player.

Advanced Embedded Programming Techniques: Data-Driven Programming

Here, I will use the MP3 player as an example to introduce the data-driven concept. To play music using an MP3 player, MP3 format files are required, and different songs will follow this format and be stored sequentially.

The corresponding MP3 player will parse the MP3 music files accordingly, so that different music files are parsed in a unified manner without needing to switch to another parsing method. In the future, if we want to play other music, we only need to add the corresponding music files without needing to update the music player.

At the same time, when we need to change songs, define playback modes, etc., we only need to logically process the playback file index. This example demonstrates the characteristics of the data-driven concept: it considers data to be variable while logic is relatively fixed, thus separating data from logic, reducing code logic repetition, and enhancing code cohesion.

2. Data-Driven Implementation Framework Diagram

In a previous article, I mentioned a clever point when introducing structures; I wonder if everyone still remembers? <【Collection】Advanced Tips on Structures Used by Experts>. In that article, I mentioned that structures can encompass all data, and almost all things can be abstracted into data. Therefore, adopting a data-driven development approach will also be an effective strategy.

Advanced Embedded Programming Techniques: Data-Driven Programming

Analysis:

  • The left side contains all the data, including user inputs, collected data, and various data processing methods. After obtaining all the data, the normal approach is to directly code for data parsing to meet project requirements.

  • However, for data-driven development, we do not immediately parse the data; instead, we first design the database. Here, the database I refer to is not something like MySQL, but a data structure that indicates the relationships between data, similar to the MP3 format files mentioned earlier.

  • After designing the database, we need to construct the method for parsing the database, which aims to achieve all or part of the project functionality, similar to the MP3 player mentioned earlier.

3. Implementation Collection

The biggest challenge in data-driven programming lies in abstracting the database and data parsing (which is somewhat similar to a text parser). The flexibility of the design of these two parts determines the program’s extensibility and compactness.

Currently, a relatively simple approach is to use arrays as databases, with data parsing essentially being a table lookup. Therefore, many people directly refer to it as table-driven programming. However, data-driven programming can be designed to be much more complex than table-driven programming, which is also a deciding factor in choosing the data-driven method for coding during development.

Below, I will analyze a relatively basic example:

1. Implementation of a State Machine

Reference Demo:

 1#include <stdio.h>
 2#include <stdlib.h>
 3
 4// Construct data  
 5#define STATUE1    (0) 
 6#define STATUE2    (1) 
 7#define STATUE3    (2) 
 8#define MAX_STATUE (3) 
 9
10int Statue1Process(int param);
11int Statue2Process(int param);
12int Statue3Process(int param);
13/***************************************
14 * Function: Data-driven programming example  
15 * Author :(WeChat: Last Bug) 
16 ***************************************/
17 // Construct database
18typedef int (*PStatueMachineProcess)(int param);
19PStatueMachineProcess MachineProcess[MAX_STATUE] =
20{
21    Statue1Process,
22    Statue2Process,
23    Statue3Process  
24};
25
26// Construct data 
27int Statue1Process(int param)
28{
29    printf("Statue1Process\n");
30    return STATUE2;
31}
32
33int Statue2Process(int param)
34{
35    printf("Statue2Process\n");
36    return STATUE3;
37}
38
39int Statue3Process(int param)
40{
41    printf("Statue3Process\n");
42    return STATUE1;
43}
44
45
46int main(int argc, char *argv[]) {
47
48    int statue = STATUE1;
49    int count = 0;
50
51    // Database parsing and logic guidance 
52    while(1)
53    {
54        statue = (MachineProcess[statue])(0);
55        count++;
56        if(count > 10)break;
57    }
58
59    printf("WeChat: Last Bug\n");
60
61    return 0;
62}

Analysis:

  • Implementing a state machine this way should be much more convenient than using if-else. The above code, for those with some programming experience, seems to have simply used a function pointer to achieve it. If we analyze it carefully, we can see that during this process, only the state data has changed, while everything else is bound to a coherent process. Here, the state data serves as the identifier for the array, which also illustrates the characteristics of data-driven programming: it is only sensitive to data.

  • From the above processing, we can see that this method can reduce the use of switch and if-else statements.

2. Message Processing Mechanism

Reference Demo:

 1typedef enum
 2{
 3    OBJ_TYPE_1,
 4    OBJ_TYPE_2,
 5    OBJ_TYPE_3,
 6}ENUM_OBJ_TYPE;
 7
 8typedef enum
 9{
10    SIG_TYPE_1,
11    SIG_TYPE_2,
12    SIG_TYPE_3,
13}ENUM_SIG_TYPE;
14
15typedef int (*MessageProcess)(int param);
16
17typedef struct  _tag_MessagePack 
18{
19    ENUM_OBJ_TYPE       ObjType;    // Object type  
20    ENUM_SIG_TYPE    SignalType;    // Message type
21    MessageProcess   MessageProc;   // Message processing 
22}sMessagePack ;
23
24int obj1_Sig1_proc(int param)
25{
26
27} 
28.....
29 /***************************************
30 * Function: Construct database 
31 * Author :(WeChat: Last Bug) 
32 ***************************************/
33sMessagePack stMessagePack[]= 
34{
35    {OBJ_TYPE_1, SIG_TYPE_1, obj1_Sig1_proc},
36    {OBJ_TYPE_1, SIG_TYPE_2, obj1_Sig2_proc},
37    {OBJ_TYPE_2, SIG_TYPE_1, obj2_Sig1_proc},
38    {OBJ_TYPE_2, SIG_TYPE_2, obj2_Sig2_proc},
39    {OBJ_TYPE_3, SIG_TYPE_1, obj3_Sig1_proc},
40    {OBJ_TYPE_3, SIG_TYPE_2, obj3_Sig2_proc}
41};
42
43/***************************************
44 * Function: Message loop processing 
45 * Author :(WeChat: Last Bug) 
46 ***************************************/
47MessageProcess MessageLoop(ENUM_OBJ_TYPE objType, ENUM_SIG_TYPE signalType)
48{
49    int i = 0;
50    for (i = 0; i < (sizeof(stMessagePack)/sizeof(sMessagePack)); i ++)
51    {
52        if ((stMessagePack[i].ObjType == objType) && (stMessagePack[i].SignalType == signalType))
53        {
54            return stMessagePack[i].MessageProc;
55        }
56    }
57    return NULL;
58} 

Analysis:

  • The above code is just a simple experience of the data-driven programming method. The author has not considered efficiency too much; its performance is related to the designed data structure. This approach also helps avoid many people’s habit of hard coding.

4. Conclusion

Finally, data-driven programming is not a panacea; it may have adverse effects on some designs. It is generally used for implementing relatively clear logic processing. However, it is very useful for simplifying conditional statements, so this programming approach should be chosen based on specific situations, and a strong understanding of the target project is also necessary.

Alright, here is the WeChat account:“Last Bug”, a technical knowledge enhancement base for everyone. I also want to thank all the supporters; see you in the next exciting issue!

Advanced Embedded Programming Techniques: Data-Driven Programming

Recommended Articles Click the blue text to jump

☞【Killer Technique】 Using “Universal C Programming” to lead into “Object-Oriented Programming”Advanced Embedded Programming Techniques: Data-Driven Programming

【C Advanced】 Pay attention to “Shift Operations” in Embedded Development!Advanced Embedded Programming Techniques: Data-Driven Programming

☞【Must-Read】 The Path Every Embedded Engineer Must Take — “Synchronization Issues”Advanced Embedded Programming Techniques: Data-Driven Programming

☞【Heavyweight】 Analyzing MCU’s IAP Upgrade Software Design (Design Thinking Part)

☞【OS】 These concepts in the “File System” can be understood this way

☞【Collection】 Homemade Small GUI Framework (Design Philosophy Part)

☞【C Advanced】 I heard that using the “Comma Expression” is just to show off skills?

☞【Classic】 Diagnosing C Advanced Techniques in printf

☞【Open Source Interpretation】 A Lightweight C Logging Library – EasyLogger

Leave a Comment