开发者

C++, How to maintain both data locality and well splitted code structure at every layer of a program?

开发者 https://www.devze.com 2022-12-20 12:58 出处:网络
In my recent project I have a class like this: class layer1 { myclassa l1dataa; // layer1 data ... myclassn l1datan;

In my recent project I have a class like this:

class layer1 {
myclassa l1dataa; // layer1 data
...
myclassn l1datan;

public:
void l1datatransformsa()
{
  myotherclassa l2dataa; // layer2 data
  ...
  myotherclassn l2datan;

  many operations; // way too many operations for a single method
}

void l1datatransformsb() {}
};

The method l1datatransformsa invokes local data and is quite long and robust. I would like to divide its code into smaller meaningful portions (methods) which all work on the same local layer2 data. It can be done in few ways, though none of them seems good enough to me, therefore I'm asking for recommendation on how should it be done:

  • Breaking the code of "many operations" into private methods of class layer1.

Cons: I would have to pass as arguments to those new methods references to all layer2 data, which is not very elegant as there is too many of them

  • Rewriting the method l1datatransformsa as a nested class of class layer1 with layer2 data declared as its data members.开发者_C百科 Then it would be possible to split "many operations" into members of the nested class.

Cons: To access layer1 data from nested class I would have to use reference or pointer to the instance of enclosing class. This will make me include many changes in the code of "many operations" and will make the code less clear. It would be even worse if one would think of a need of splitting in the same manner one of methods of nested class.

The basic idea behind all this is to have a comfortable way of keeping your local data close to the functions or methods which use it and only to them at every layer of your program.

ADDED: "many operations" which we we want to split work both on almost all data members of class layer1 and all local data layer2. They work on layer2 data sequentially and that's why they can be splitted easily, though it's a bit awkward 'programistically'.


First of all, you can increase the clarity of your code by defining your class in a header file, using only prototypes for member functions, and writing the member functions in a separate .cpp file. I'm assuming that you combined these for the sake of making it easier to post here.

The method l1datatransformsa invokes local data and is quite long and robust. I would like to divide its code into smaller meaningful portions (methods) which all work on the same local layer2 data.

You might be approaching this incorrectly. If you are only wanting to break down a large member function for the sake of sanity, then all you need are functions, not members. Every function associated with a class is not required to be a member. Only use members here if you will need to call these sub-routines explicitly and individually from somewhere other than inside another member function. When you write your helper functions in the same .cpp file as your class' member functions, declare them static and they will only operate within the scope of that file (effectively limiting them to that class but without giving them the unobstructed data access of a member function). This is an easy way to enforce restrictions on data access as well as promote modularity. Each sub-function will only operate on data passed through the function's parameters (as opposed to a member function which can access all of the class' member data freely).

If you find yourself needing to pass a large number of parameters to a single function, ask yourself if you should A) store them in a struct instead of independent variables and pass the struct to the function or B) break apart the function into several shorter, more focused functions that perform their task on a sub-set of the variables. If these are member variables and you still want to access them individually but pack them into a struct, don't forget you can make the struct private and write simple getter/setter functions for accessing the individual values.

Keep the functions focused; each should do a single task, and do it well. Small functions are easier to read, test, and debug. Don't be afraid to break up your code into several nested layers (l1datatransformsa calls helper func A, which calls helper func B, etc) if it makes the code clearer. If you can write a relatively short name for the function that describes clearly and exactly what the function does (encryptString() or verifyChecksums() instead of dataProcessingStepFour()), you are probably on the right track.

TL:DR version: I don't think nesting a second class is the answer here. If, as you say, the nested class will need to access members of the parent class, that throws up a flag in my head that there is a better way to organize this (classes should function independently and should never assume that they are a child of an object of a particular type). Personally, I would keep l1datatransformsa relatively brief and use helper functions (not member functions) to do the work. If you are needing to pass a lot of different variables to helper functions, either use a struct instead of loose variables or re-think whether that sub-function needs all that information or if it can be split into smaller functions that each operate on less data.


I would conceptualize it, then break up data layers based on conceptual actions and models.


-- New answer --

I removed my old answer because I thought you were looking for a trivial tips. I think you need to do some reading on the tools and techniques you have available to organize and construct software.

  1. Gang Of Four - Design Pattern Book
  2. Modern C++ Design
  3. Generic Programming

The first book is essential, the second builds up some of the concepts that are introduced in the first in C++. The third is quite academic -- but contains a wealth of information, you can probably ignore it.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号