The designing and implementation are the most important part of the software life cycle, and plays very vital role Object Oriented approach specifically. Since the approach itself has to provide reusability, extensibility. So it is very important to design and implement the software in manner which lead to none/minor changes in forthcoming versions of the software and reduce the redundancy and duplication of code.
Here are the few best practiced patterns which may help you to check so called “Code Bloat”. Patterns are here presented as context, solution, example and motivation:
Decompose Conditional
Extract Class
Extract Method
Move Field
Move Method
Pull Up Method
The presented patterns are identified from a large collection of publicly known patterns. As those that most likely cause code size to shrink. Some of the patterns are more
concentrated on the actual implementation. Those are described in terms of C++ code examples. The rest of the patterns belong clearly to the design level. They are described with diagrams in Unified Modeling Language (UML) notation.
Decompose Conditional
Context:
You have a complex conditional (if-then-else) statement.
Solution:
Extract the condition into its own method. Extract the then part and the else part into their own methods.
Example:
Original: if( static_cast< CEikFloatingPointEditor* >( Control(
...EConverterEditor1 ) )->TextLength() == 0 )
{
iLastEditorUsedForUserInput = EConverterEditor1;
iModel->SetSelectedEditor( 0 );
ShowResultL();
}
else if( static_cast< CEikFloatingPointEditor* >(
...Control( EConverterEditor2 ) )->TextLength() == 0 )
{
iLastEditorUsedForUserInput = EConverterEditor2;
iModel->SetSelectedEditor( 1 );
ShowResultL();
}
Refactored: if( !IsFloatEntered( EConverterEditor1 ) )
{
SetLastEditor( EConverterEditor1 );
}
else if( !IsFloatEntered( EConverterEditor2 ) )
{
SetLastEditor( EConverterEditor2 );
}
TBool IsFloatEntered( TInt aEditorId )
{
...
}
void SetLastEditor( TInt aEditorId )
{
...
}
Motivation:
Conditional logic is usually the most complex area of a program
There is a good possibility that there are similar conditional statements elsewhere in the program and the extracted methods can be re-used there.
Extract Class
Context:
You have one class doing work that should be done by two.
You have a large class that tries to do everything.
Solution:
Decide how to split the responsibilities of the class.
Create a new class and move the relevant fields and methods from the old class into the new class.
If the original class is part of a public interface, you have to provide wrapper methods in place of the moved me
Example:
Motivation:
A large class is too big to understand easily. The lack of understanding causes accelerated growth when the class is modified.
Clearly defined classes tend to stay small and are easier to maintain there.
Extract Method
Context:
You have a code fragment that can be grouped together.
Copy-paste coding: The same fragment shows in multiple methods.
Solution:
Turn the fragment into a method whose name explains the purpose of the method.
Example:
Original:
void FetchFirstItemL( TPtr& aName, TReal& aValue )
{
TInt index = DoSomeImportantStuff();
aName = view.ColDes( index++ );
aValue = view.ColReal( index++ );
}
void FetchOtherItemL( TPtr& aName, TReal& aValue )
{
DoSomethingElse();
aName = view.ColDes( 0 );
aValue = view.ColReal( 1 );
}
Refactored: void FetchFirstItemL( TPtr& aName, TReal& aValue )
{
TInt index = DoSomeImportantStuff();
FetchNameAndValue( aName, aValue, index );
}
void FetchOtherItemL( TPtr& aName, TReal& aValue )
{
DoSomethingElse();
FetchNameAndValue( aName, aValue, 0 );
}
void FetchNameAndValue( TPtr& aName, TReal& aValue,
TInt aColumnIndex )
{
aName = view.ColDes( aColumnIndex++ );
aValue = view.ColReal( aColumnIndex++ );
}
Motivation:
Copy-paste coding is one of the worst cases of code bloat:
Because the same code is copied to several places, all modifications to the code fragment must also be done several times.
Missing one fragment causes a potential bug.Any existing bugs will also be copied along.
Move Field
Context:
_A field is, or will be, used by another class more than the class on which it is defined.
Solution:
Create a new field in the target class, and change all its users.
Move also the getter and setter methods for that field where appropriate (see Move Method pattern).
Example:
Original
class CUiView: public CCoeControl
{
public: // Methods
...
}
void CUiView::Draw() const
{
TSize mySize = iParent->ViewSize();
TPoint myPos = iParent->ViewPosition();
TRgb myColour = iParent->ColourMap()->ViewColour();
gc.FillRect( myPos, mySize, myColour );
}
Refactored:
class CUiView
: public CCoeControl
{
public: // Methods
...
private: // data
TSize iSize;
TPoint iPoint;
TRgb iColour;
}
void CUiView::Draw() const
{
gc.FillRect( iPos, iSize, iColour );
}
Motivation:
“Unnecessary” getter and setter method calls cause overhead that shows in performance and on the binary size.A field in the “wrong” class causes many dependencies that could be avoided.
Move Method
Context:
A method is, or will be, using or used by more features of another class than the class on which it is defined.
Solution:
Create a new method with a similar body in the class it uses most.
Either change the old method into a delegation, or remove it altogether.
Example:
Original:
void CUiControl::Draw() const
{
TRect rect = iBox->Rect();
TRgb fgColour = iBox->FgColour();
TRgb bgColour = iBox->BgColour();
gc.FillRect( rect, fgColour, bgColour );
}
Refactored :
void CUiControl::Draw() const
{
iBox->Draw();
}
void CBox::Draw() const
{
gc.FillRect( iRect, iFgColour, iBgColour );
}
Motivation:
Moving methods is necessary when classes have too much behavior (i.e. are too large) or when classes are too tightly coupled.
Removing method calls that are required to access, for example, private member variables of another class, reduces the binary size. Method calls are always more expensive than member variable access in terms of generated machine code size and software performance.
Pull Up Method
Context:
You have methods with identical results on subclasses.
Solution:
Move them to the base class.
Example:
Motivation:
Eliminating duplicate behavior is important. It reduces code bloat and increases maintainability.
Making modifications to similar code in several places risks that some of the places are missed and potential bugs are introduced.
|