I need to implement a set of algorithms for data processing. Algorithms do not directly access data, but use a set of basic operations that are placed in a separate class. The following code can be considered as an MWE:

class Data { .. }
class BasicOperations {
    void f(Data d) { .. }
    void g(Data a, Data b) { .. }
    void h(Data a, Data b, Data c) { .. }
    // ...
class Algorithm {
    void run(Data d1, Data d2, BasicOperations ops) {
        // call ops.f, ops.g, ops.h

It is worth noting that BasicOperations depends on the internal representation of the Data class. This is due to the desire to separate the basic data operations from the data itself. But even if I merge the Data and BasicOperations classes, the problem described below will not disappear.

However, there are several ways to store data. This leads to the fact that the Data and BasicOperations classes should become abstract or interfaces, and the various storage formats and basic operations corresponding to these storage formats should be designed as child classes. This leads to something like the following kind of code:

abstract class Data { .. }

class Data1 : Data { .. }
class Data2 : Data { .. }

interface BasicOperations { .. }

class BasicOperations1 : BasicOperations { .. }
class BasicOperations2 : BasicOperations { .. }

An abstract factory is used to create objects. The methods of the BasicOperations1 and BasicOperations2 classes receive as arguments instances of the abstract Data class, and not the Data1 and Data2 classes, respectively. Since using the factory guarantees type matching, it would be possible to use dynamic_cast, but it is slow and there is not always has RTTI. As noted earlier, it would be possible to put BasicOperationsN methods inside the DataN class, but this would not eliminate the problem that the arguments are instances of the abstract Data class, and not DataN.

Is it possible to modify the architecture in any way so as to get rid of the existing problems, that is, from the need to use RTTI?

2 Answers 2


However, there are several ways to store data.

This has always been true. And there has only ever been one acceptable way to store data that is meant to be used. The expected way.

If you are stuck with data actually stored several ways you can either throw out data that violates your expectations or expect all these ways.

A bad way to manage M things expecting N ways is to write MxN things to handle everything.

One way to manage a need to expect N ways is to adapt N ways into one way. Then M things can expect the one way once your N adapters have done their work.


Classes should be independent. But that is not a must. You can build two classes that are designed to work together, and that need to know each others internals. In Swift, you can put two such classes into one file and make members “fileprivate”, that is public within the file and private outside.

In C++ you can use “friend” declarations. Or instead of member functions of a class T, which Must be declared in a header file, you can have a function f (T& tthis, parameters).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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