Eight-Bit OO (Hard Eight)



Eight-Bit OO (Hard Eight)

Marshall Meier

Using object-oriented techniques to design software for an 8-bit microcontroller may not be common, but it can be effective. This article tells how one project did it and what they learned.

This is a case study of an actual embedded software project that applied an object-oriented analysis and design (OOAD) approach, without using an object-oriented language to implement the design. The project will be referred to as the Zeppelin project, and the product will be referred to as the Gruntmaster (in honor of Dilbert).

The software team for project Zeppelin currently consists of one project manager, six software engineers, and three software test engineers. Industry experience among team members ranges from six months to over 20 years. At the beginning of the project, only one team member had worked on a project that performed object-oriented analysis and design. To address this problem, all of Zeppelin's team members attended a five-day OOAD with UML class, presented by Lockheed Martin's Advanced Concepts Center division (www.acc-lmco.com).

Battle of the life-cycle models
Towards the beginning of the project, Zeppelin followed a classical waterfall life-cycle model as seen in Figure 1. Adhering to the waterfall model had its advantages. First, the waterfall model is the dominant software life-cycle model used at the company. All of the team members were familiar with the waterfall model and felt comfortable following it. Second, the waterfall model is a disciplined approach. Third, as documentation is an integral part of the model, good documentation is always available. This leads to easier product maintenance once the Gruntmaster has entered its maintenance phase.

Adhering to the waterfall model on Zeppelin also had its disadvantages, though. First, as seen in Figure 1, all of the design is completed before coding begins. This means that some design defects may not be found until the code phase. Since Zeppelin's team members did not have experience using an object-oriented design approach when the project began, it was likely that many design defects would not be caught until the implementation phase. Second, and more important, the waterfall model did not align with Zeppelin's hardware schedule. Clearly, we needed to find another life-cycle model.

Enter the incremental life-cycle model. In the incremental model, “the product is designed, coded, and tested as a sequence of incremental builds, where a build consists of code pieces from various modules interacting together to provide a specific functional capability.”1 The incremental model has several advantages. First, operational-quality software is produced at each phase. Second, portions of the total project are available much sooner. Third, it adapts well to changing requirements. The incremental model does have it disadvantages, though. The team has to be sure that the incremental model does not turn into a “build and fix” death march. The model also requires more integration work.

Figure 2 illustrates the incremental model followed by the Zeppelin team. Each increment box contains detailed design, implementation (that is, code), unit test, and integration. Zeppelin's project team decided that an object-oriented development, combined with the incremental life-cycle, would work best. However, there was a problem. The Gruntmaster did not have the hardware resources to run software written in an object-oriented language such as C++ or Java. The challenge then became performing an object-oriented analysis and design, and implementing that design with the C language. Our basic rule of thumb became: adhere to the OO paradigm when possible, but be willing to deviate from it when necessary.


UML
The Zeppelin team represented their object-oriented design with the Unified Modeling Language (UML). UML is considered the standard OO-modeling language. The team selected Rational's Rose Modeler 98i as a UML CASE tool.

OO-to-C translation
Since the team could not write the Gruntmaster's software in an OO language, a technique or strategy was required to translate the UML diagrams into C. The object-oriented paradigm is defined by three main principles: encapsulation, polymorphism, and inheritance. It was thought that any translation technique would need to accommodate for those three principles in C.

The project team first explored using the Samek Macros.2 The Samek macros can be used to give C a more “C++ look.” The macros also allow C to implement encapsulation, polymorphism, and inheritance. Unfortunately the macros are very pointer-intensive. Given the Gruntmaster's limited resources, the macros unfortunately weren't an option.

Next the team tried to take some of the key principles of the Samek macros and come up with their own, less pointer heavy, translation scheme. This was accomplished, although inheritance would no longer be supported. The team felt the loss was acceptable. A prototype using the new technique was implemented. But again the cost of the pointers was just too high. Rats, foiled again.

UML-to-C translation, take three. The team analyzed their latest technique and discovered that any sort of polymorphism scheme was going to require too many pointers. So polymorphism was scrapped. Nuts. Due to inexperience with objects, the team didn't realize at the time that polymorphism and inheritance would have greatly simplified the final design.

But we still had encapsulation. If the team could devise a strategy that supported the encapsulation principle, they'd be in business. Fortunately the C language has a few key constructs that support encapsulation. The UML-to-C translation process would take the form of the project's coding standard.

The coding standard
The idea of the coding standard was to provide a recipe for converting a class modeled in UML to C code (shown in Figure 3). The key issue was how to represent a class in C. A class consists of attributes (variables) and methods (functions). Our translation from UML to C used the following standards:

  • Each class will consist of three files: a Class_Name.h , a _Class_Name.h , and a Class_Name.c
  • The class's public definition will reside in Class_Name.h . This includes the class's public attribute declarations and public method prototypes
  • The class's private definition, including private attributes, macros, #defines , and static declarations will reside in _Class_Name.h
  • The class's implementation will reside in Class_Name.c
  • Structures will be used to group a class's attributes types. This will be enforced via the Lint “strong types” feature
  • Public method names will take the form cClass_Name_method_name() , with an underscore separating the class and method names
  • Private methods will be declared as static. That way they cannot be used outside of the Class_Name.c file. Their names will take the form _cClass_Name_method_name()
  • Private attributes will be placed in their own structure. The structure's name will take the form _cClass_Name
  • Public attributes will be avoided whenever possible because they compromise information hiding
  • If public attributes are necessary, they will be placed in their own structure. The structure's name will take the form cClass_Name

Unfortunately, no tool was available to automate the translation from UML to C. To ensure that the coding standard was followed, all code was peer reviewed.

Example
Figure 4 and Listing 1 show how the coding standard translates UML to C. The astute reader will realize that this implementation allows only one instance of each class. There are certainly ways of getting around this (for example, passing a pointer to the object to be manipulated). But again, this involves a lot of pointers. After a lengthy discussion, the team decided that this situation would be acceptable for the Gruntmaster's implementation.

Listing 1 Translating from UML to C
/* File name: _vcr.h *//* Private attributes */typedef struct {   tMode mode;   /* Playing or Stopped */   tButton play_button;   tButton stop_button;} _cVCR/* Private methods */boolean _cVCR_get_tape_present(void); /* returns true if tape is in the VCR *//* File name: vcr.h */#include _vcr.h/* Public methods */void cVCR_constructor(void);void cVCR_play(void);void cVCR_stop(void);void cVCR_set_time(void);void cVCR_eject_tape(void);/* define TAPE_PRESENT register#define TAPE_PRESENT 0x04/* File name: vcr.c */#include vcr.h/* Declare object */_VCR _oVCR;/* Private method implementations (a couple of examples) */static boolean c_VCR_get_tape_present(void);{   if(TAPE_PRESENT)   /* Check tape present register */   {      return true;   }   else   {      return false;   }}void cVCR_play(void){   _VCR.mode = playing;}

Lessons learned
Overall, using an object-oriented approach worked well. It provided an excellent framework for the design to be created, but the project certainly wasn't flawless. Performing an object-oriented analysis and design can be a complex process. Implementing that design in C adds even more complexity. That, combined with the team's inexperience with OO, yielded several “lessons learned” (including what worked and what didn't). These lessons are shared here to hopefully prevent future teams from repeating them:

  • Be careful that the object-oriented design doesn't turn into a structured design. This can happen if the team does not have a strong background in object technology
  • Write the coding standard before design begins. This will help point out limitations in the implementation that may affect the design, such as not having inheritance. It also ensures that a consistent naming style exists between UML diagrams and code
  • Write a UML diagramming standard. At first this may not seem necessary when using the Unified Modeling Language, but it is. UML does not address all of the issues facing embedded developers. The most frequent example of this that the Zeppelin team ran into was how to model ROM-only tables. Tables are a common construct in embedded systems, but UML doesn't readily support their modeling. It would have saved the Zeppelin team time to have decided how to model tables, and capture that in a diagramming standard, before the design work began
  • Know how much detail to put in the design. Even more important than this is to design at a consistent level of detail
  • Develop objects not only in order of importance, but also in order of frequency of use. The Zeppelin team had identified an object that would handle the Gruntmaster's non-volatile (NV) memory. All other objects in the system used this object. By developing this object first, the team would have saved time by not having to “stub out” calls to the NV object
  • Review, review, review. Reviewing both the UML design and resulting code was one of the smartest things the Zeppelin team did. Through informal walkthroughs, the team was able to find and eliminate scores of defects before testing started. Figure 5 shows actual data from the project


Not a silver bullet
Object-oriented technology is by no means a silver bullet. Just because software is object-oriented, doesn't mean that it is of high quality. Rather than preaching that “object-oriented design is the only way to develop software,” I hope this article demonstrates that it is possible to design and implement embedded software using object-oriented techniques.

Marshall Meier has a BS in computer science and is working on a MS in software enginnering. He is currently a partner with Third Wave Partnership (www.twp-llc.com), a consulting firm in Minneapolis. He can be reached at .

Works cited
1. Schach, Stephen R. Classical and Object-Oriented Software Engineering, 4th edition. New York: McGraw-Hill, 1999.

2. Samek, Miro, “Portable Inheritance and Polymorphism in C,” Embedded Systems Programming, December 1997, p. 54.

3. “Introduction to Software Engineering,” NASA Software Engineering Laboratory. December 5, 1999. Available at sweng.larc.nasa.gov/larcse/sld039.htm.

Figures


To download a PDF of the original print article, click here.
Do not use or repost this PDF and article html without explicit permission from editorial director of Embedded.com, UBM Electronics, UBM plc. Copyright © 2012, UBM plc.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.