When my program is very young, there are usually many functions that do simple things.
When it became older, I found that it is more convenient to bundle some similar functions together, and group the return results of old functions as a "Report".
The "Report" can be easily passed around as a communication package among different modules.
Code V1
class B{
float getWidth(C c){
float width= ... (very cheap function about "c") ;
return width;
}
float getHeight(C c){
float height= ... (very cheap function about "c") ;
return height;
}
};
Code V2
class ReportSize { float width; float height; }
class B{
ReportSize getSize(C c){ //<-- grouped
float width = ... ;
float height= ... ;
return ReportSize(width ,height);
}
};
Code V1
class D{
Vector3 calculateNarrow(){ ... }
Vector3 calculateBoard(){ ... }
};
Code V2
class ReportVector3Pair{
Vector3 resultNarrow;
Vector3 resultBoard;
Vector3 get(NARROW_OR_BOARD paramEnum){
//return "resultNarrow" or "resultBoard"
}
};
class D{
ReportVector3Pair calculate(){ ... } //<-- grouped
};
The refactoring cost some development time. All locations of code (up to 100 callers) have to be manually refactored to match the new signature.
How to minimize the chance of the need to refactor it later? How to minimize cost of the refactoring if it may happen in future?
How to minimize the chance of the need to refactor it later?
Create non-member functions that can return higher level objects instead of changing existing classes.
For example, instead of writing V2 of B
, keep the existing B
and use:
class ReportSize { float width; float height; }
ReportSize getReportSize(B const& b, C c)
{
return {b.getWidth(c), b.getHeight(c)}
}
Similarly, instead of creating V2 of D
, keep existing D
and use:
Vector3 calculate(D const& d, NARROW_OR_BOARD paramEnum) {
//return "resultNarrow" or "resultBoard"
}
How to minimize cost of the refactoring if it may happen in future?
Use non-member functions to extend functionality instead of modifying existing classes.
According to Scott Meyers, using non-member functions improves encapsulation.
Using non-member functions to add new functionality also follows The Open/Closed Principle.