Design of small related classes

R

Richard Pope

I have some existing code that I am trying to upgrade to c++. The data in
question is two bytes, which are used to identify what information is
requested from an industrial computer (a PLC). The first few bits represent
the "category" of the data, and determine how the rest of the two bytes are
interpreted.

The existing code extracts various details from the data, but always uses a
switch statement on the category.

I could write a single class in c++, but I would have a switch statement in
every member function. This doesn't feel right somehow.
I could have a class for each category (inheriting from an ABC) but how do I
use them in practise? Do I need some kind of factory class that creates the
correct class, based on the category it extracts from the data?
 
P

Phlip

Richard said:
I have some existing code that I am trying to upgrade to c++. The data in
question is two bytes, which are used to identify what information is
requested from an industrial computer (a PLC). The first few bits represent
the "category" of the data, and determine how the rest of the two bytes are
interpreted.

The existing code works. Leave it alone.

If you need the ability to easily change the code, write an emulator for
this hardware, then write lots of tests

If you need to improve other code's ability to call this code, wrap it in
"Facade" from the book /Design Patterns/.

There is no benefit to making a design "more OO" just for the sake of
changing it. And hardware generally dictates the design of code accessing
it. Just make sure that all other code in your system only calls the
interface of your Facade, and never gets its paws on any of those low-level
variables.
The existing code extracts various details from the data, but always uses a
switch statement on the category.

I could write a single class in c++, but I would have a switch statement in
every member function. This doesn't feel right somehow.
I could have a class for each category (inheriting from an ABC) but how do I
use them in practise? Do I need some kind of factory class that creates the
correct class, based on the category it extracts from the data?

Oh. Okay, in that case, you are correctly following this design rule: Never
use switch statements, except at an applications' boundary. Use either
Abstract Factory, Class Factory or Prototype Design Pattern to convert that
data, once, into an object. That will be the last switch statement. From
then on, only call virtual methods. Look up the refactor "Replace Type Code
with Subclasses" from the book /Refactoring/.
 
D

Daniel T.

Richard Pope said:
I have some existing code that I am trying to upgrade to c++. The data in
question is two bytes, which are used to identify what information is
requested from an industrial computer (a PLC). The first few bits represent
the "category" of the data, and determine how the rest of the two bytes are
interpreted.

The existing code extracts various details from the data, but always uses a
switch statement on the category.

I could write a single class in c++, but I would have a switch statement in
every member function. This doesn't feel right somehow.
I could have a class for each category (inheriting from an ABC) but how do I
use them in practise? Do I need some kind of factory class that creates the
correct class, based on the category it extracts from the data?

Assuming that a particular bit of data never changes its "category" then
yes, I would probably use inheritance. You should have a factory method
that contains a switch statement that constructs a particular sub-type
based on the category. This function should return an auto_ptr<Base>
object.
 
S

Siemel Naran

Assuming that a particular bit of data never changes its "category" then
yes, I would probably use inheritance. You should have a factory method
that contains a switch statement that constructs a particular sub-type
based on the category. This function should return an auto_ptr<Base>
object.

Fine. Note that the factory method can use a table lookup (eg. a map<id,
object*>) instead of a switch. And a counterargument: the virtual pointer
is 4 bytes on a typical Intel/AMD box, whereas the original type is 2 bytes
(though who knows -- maybe there were 2 bytes padding).
 
D

Daniel T.

Siemel Naran said:
two bytes


But it is properly factored? In each member function he has a switch
statement on the two bytes that represent the type.

I think that depends... How many switch statements are there off of this
type, and are they all in the same class or spread out all over the
place?

I personally would probably factor the switch statements out just
because I don't like the code duplication, but depending on time
constraints and the likelihood that more types will be added in the
future, I may leave the switch statements in and call it "good enough".

Refactoring is great for making code easer to change, however if there
is no pressure for the code to change, there is little need to refactor.
 
D

Daniel T.

Siemel Naran said:
Fine. Note that the factory method can use a table lookup (eg. a map<id,
object*>) instead of a switch.

I would only go that far if for some reason I needed to dynamicly change
what kind of object needs to be created for each type. Otherwise, one
switch statement does not constitute code duplication.

And a counterargument: the virtual pointer
is 4 bytes on a typical Intel/AMD box, whereas the original type is 2 bytes
(though who knows -- maybe there were 2 bytes padding).

Good point, for this small of an object. The OP said the entire chunk of
data was only 2 bytes, the identifier was just a "few bits". Going with
inheritance would jack up the size of the object by quite a bit. More
than double...
 
L

lilburne

Daniel said:
Refactoring is great for making code easer to change, however if there
is no pressure for the code to change, there is little need to refactor.

Refactoring also offers the opportunity for adding new bugs. If the code
works it don't need fixing.

Only refactor code if it requires changing anyway. Then integrate the
refactored code into the product, running all the tests, before
embarking on the task that called for the refactoring in the first
place. Don't combine refactoring with bug fixing or code enhancement, if
it all goes tits-up you'll not know whether it was the refactoring or
the other changes that were responsible.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top