2

I have a project in C that I'm looking to convert to C++. The project does white box hardware testing of a device (actually many similar devices). In this case the device has two processors. Each have unique capabilities and both have some similar features (discrete io and such). The top level test code is a collection of exported functions from a DLL.

Looking at the code knowing that I'll have to support additional variants of the devices I have the following questions which made me think others would have suggestions on architecture/design and the reasoning behind those design choices will help others:

  1. Do you support a device class with members proc_a and proc_b (has a thinking) with the interface having distinct function names so it's clear to the user what's being manipulated or prefer the interface to have a more generic naming scheme (like setDiscrete which takes an enum encompassing both processors' discrete a (DISCRETE_PROC_A_x and _B_x)?

  2. Knowing that future variants of the device will have updated processor(s) how do I keep the changes to only those features that changed? I.e. A new processor B adds functionality and the include files for that functionality (from the embedded source) are different then what is used so far. I'm thinking I make the processor a class and than children of it to handle this concern. Is there a more maintanable design? What if the interface for that class needs to change but the same functionality is needed?

  3. Tell don't ask is great but when you need setters or getters do you prefer set/get, push/pull, set/clear, etc? Do you make some communicate with the device and cache the state in your class? If so, is that separate fetch function and you use a state tracking variable or is it another function in the interface?

  • I am not sure that converting a project from C to C++ is worthwhile. Since C++ is compatible with C, you might simply write new modules in C++. – Basile Starynkevitch Aug 6 '15 at 8:41
  • A bigger problem is that, while it is possible to use C++ in the implementation of a DLL project, the interface that is exposed by a DLL must be a pure extern C collection of non-member functions, because any export of C++ types require a runtime dependency on the same version of the C++ Standard Library Runtime, which defeats all of your wishes for forward compatibility (or the hope of isolating platform variations from the clients of your API). – rwong Aug 6 '15 at 8:46
  • Grasshopper: please improve the title of your question to make it more specific (regarding hardware variations that are exposed on the DLL API) – rwong Aug 6 '15 at 8:49
  • Basile, agreed. What I should have said is I have several projects that are in C and going forward future incarnations of those projects ( similar but not identical variations ) I'd like to have in C++. – Grasshopper Sep 17 '15 at 3:24
  • rwong, agreed the DLL does extern "C" the test functions. – Grasshopper Sep 17 '15 at 3:25
1

Looking at your direct questions, I will answer the entire question with a single link to the GoF Design Patterns -

https://en.wikipedia.org/wiki/Design_Patterns

And call out two patterns that I have repeatedly used when designing extendable software with minimal rewrite and that is that of the Decorator Pattern - https://en.wikipedia.org/wiki/Decorator_pattern and the Strategy Pattern - https://en.wikipedia.org/wiki/Strategy_pattern

To fully understand the direct answers to the questions you pose, understanding the above patterns will help to inform the following thinking.

  1. You can design your interface to be more generic, build the basic functionality shared by the devices in a concrete implementation, and then decorate the additional functionality on the discrete behaviors that are not shared.
  2. By doing the above, you restrict changes only to the new functionality. If you find that your interface must change, it likely means that your interface wasn't designed properly in your first use case. Strategy can come into play as well, if you need two processors to do functionally the same things, but on different types of inputs.
  3. The answer to this depends on how you have decided the implementations of above, with regard to the sharing of data, strategy and how you have done the decorating. Depending on what you need to share you may be able to make use of the Flyweight pattern - https://en.wikipedia.org/wiki/Flyweight_pattern

Regardless of what you decide, I hope that this drives home the importance of design when you are working with both new and old code with regards to reusable and extensible software. The is a, has a parent/child subclassing has caused great difficulty when poorly designed!

Happy Patterns!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.