Encapsulation vs structs is bad style?

I have a bunch of classes in a CUDA project that are mostly famous for struct and depend on each other in composition:

 class A { public: typedef boost::shared_ptr<A> Ptr; A(uint n_elements) { ... // allocate element_indices }; DeviceVector<int>::iterator get_element_indices(); private: DeviceVector<int> element_indices; } class B { public: B(uint n_elements) { ... // initialize members }; A::Ptr get_a(); DevicePointer<int>::iterator get_other_stuff(); private: A::Ptr a; DeviceVector<int> other_stuff; } 

DeviceVector is just a wrapper around thrust::device_vector , and ::iterator can be translated into a raw device pointer. This is necessary because custom kernels are invoked and require access to the device’s memory.

Now I really need encapsulation, but

  • raw pointers to data must be open, so classes using A and B can run custom kernels on the GPU
  • the default constructor is not needed, the device memory should be allocated automatically → shared_ptr<T>
  • only very few methods are required for A and B

So, life can be made much simpler just by using structs.

 struct A { void initialize(uint n_elements); DeviceVector<int> element_indices; } struct B { void initialize(uint n_elements); A a; DeviceVector<int> other_stuff; } 

I wonder how right I am that in the sense of encapsulation this is almost equivalent. If so, is there something that is wrong with the whole concept and might bite at some point?

+4
source share
3 answers

This is a compromise.

Using value structures can be a beautifully simple way to group a collection of data. They can be very stupid if you start to resort to many auxiliary routines and rely on them for other purposes. Be strict with yourself about when and how to use them, and they are fine. Zero methods on these objects are a good way to make this obvious to you.

You may have several classes that you use to solve the problem, I will call it a module. The presence of structural elements in the module is easy to argue. Outside the module, you should hope for good behavior. You do not have strict interfaces, so you should hope that the compiler will warn you about misuse.

Given this statement, I think they are more suitable for anonymous or verbose namespaces. If they fall into public interfaces, people tend to add sugar to them. Remove sugar or reformat it into a first-class object with an interface.

I think they are more suitable as const objects. The problem that you encounter is that you (try) to maintain the immutability of this “object” everywhere that it has been used throughout its entire life cycle. If another level of abstraction wants them with slight mutations, make a copy. The named parameter idiom is good for this.

Domain Driven Design provides thoughtful and thorough processing on this subject. It characterizes his more practical understanding of how to understand and facilitate design.

The clean code also discusses the topic, albeit from a different perspective. This is more morality .

Both are awesome books and are usually recommended outside of this topic.

+1
source

Make it simple. Do not introduce abstractions and encapsulation before you need it.

+2
source

It’s a good habit to always keep your data members private. At first, it might seem that your structure is tiny, does not have one or more member functions, and you need to expose data elements to it. However, as your program evolves, these “structures” tend to grow and spread. Before you know this, all of your code depends on the internal components of one of these structures, and a small change in it will reflect your entire code base.

Even if you need to set raw pointers to data, it's still a good idea to do this through getters. You can change the way data is processed internally, e. d. replace the raw array with std :: vector. If your data member is private and you are using getter, you can do this without affecting any code using your class. In addition, getters allow you to force a constant and create a specific piece of read-only data by returning a const pointer.

This is a little more than before, but most of the time he expects in the long run.

+2
source

Source: https://habr.com/ru/post/1393430/


All Articles