Question

Suppose I have two "modules", A, and B (I'm choosing not to use classes, because you generally can't create an instance of a module, which makes this question simpler). These modules contain methods suited for dealing with the same particular type of (arbitrary) data. Crucially, the representation/format of this data is different between A and B.

At some point we have a piece of data which is in a format which one of the two modules "understands", but the other does not, and the programmer has a desire to "convert" the piece of data from one representation to another.

For the sake of example, lets say we have data which is in a format that module A understands, but module B does not. On which of the two modules should I place the method that converts the data from "A representation" to "B representation"?


To explore the question a bit, it seems that we have to choose one of the following to be true:

  • A given module knows how to convert data from another format, to the format it understands
  • A given module knows how to convert data from the format it understands, to another format

In either scenario, in order for a conversion to take place, a given module must contain information about the data representation/format of a module other than itself in order to perform a conversion. From an OOP design or separation-of-concerns perspective, this seems like a bad idea.

Is introducing a third module, C, which understands how to convert the data between different representations, a more sane way to approach this?

Was it helpful?

Solution

It is usually better to have a module or class convert from another format to the format it understands.

While one can argue that all getters and setters are evil, it is clear that setters are more evil and problematic. Setters might

  1. cause concurrency issues
  2. throw IllegalArgumentExceptions (or similar)
  3. have complex data validation issues (nulls, valid birthday, etc...)
  4. leave the result in an indeterminate state.

Calling lots of setters on an different class or module that you don't fully understand is rife with dangers, since you don't know all the complexities. Getters rarely have any of these issues. When you convert from a B, you are only calling its getters. So, the best approach is something like (Java syntax, yours may vary)

public static A fromB(B b);   or

public A(B b)

True, there may be data validation issues with A, but A already knows about them. The programmer only needs have deep knowledge about A, not A and B.

Next, consider what happens when B changes.
They add a new required field, APIVersion. If A is converting to a B, A must change. And you are likely to forget about it.

But, if A is converting from a B, it might be able to stay the same. Depends if A cares about APIVersion. If it doesn't care, you leave it alone. If it does care, you should have already opened up an issue to add APIVersion, and it falls into that work naturally.

That said, if you have a lot of things to interconvert, A-Z, this becomes very messy.

An alternative approach is to have everybody understand some common intermediate data representation, say XML, JSON, CSV, a database, whatever makes sense for your stuff. Then, for your conversion, do something like:

  A.readXML(b.toXML());
   ...
  A.readXML(z.toXML());

OTHER TIPS

Your question is a bit vague, so there can be several answers.

First, if this is about code and all this happens inside an application then there should not be any data and conversion at all. Object-orientation does not deal with data, only objects with behavior, therefore there should not be any logic to convert anything.

Second, if this is not all code, and some external media is read, like a database, file or network, then the "module" would read that data into whatever objects it prefers. I would call that "parsing" not "converting".

Please update your question with more details if you means something else.

Licensed under: CC-BY-SA with attribution
scroll top