I
Immortal Nephi
I learn how to use refactoring code. It is interesting. I have a
question how to extract class. I focus to use extract method.
The class Main has one data member. The member function DoOperation_A
() and DoOperation_B() have long methods.
For example:
class Main
{
public:
Main() : data( 0 ) {}
~Main() {}
void DoOperation_A()
{
// Do something to maniuplate data
// Very long method
}
void DoOperation_B()
{
// Do something to maniuplate data
// Very long method
}
private:
int data;
};
I extract DoOperation_A() into four small member functions. I do
extract DoOperation_B() as well. I place them in private. Small
member functions have short methods. They are easier to understand.
They have better readability.
For example:
class Main
{
public:
Main() : data( 0 ) {}
~Main() {}
void DoOperation_A()
{
DoSubOperation_A1();
DoSubOperation_A2();
DoSubOperation_A3();
DoSubOperation_A4();
}
void DoOperation_B()
{
DoSubOperation_B1();
DoSubOperation_B2();
DoSubOperation_B3();
DoSubOperation_B4();
}
private:
void DoSubOperation_A1()
{
// Do something to maniuplate data
}
void DoSubOperation_A2()
{
// Do something to maniuplate data
}
void DoSubOperation_A3()
{
// Do something to maniuplate data
}
void DoSubOperation_A4()
{
// Do something to maniuplate data
}
void DoSubOperation_B1()
{
// Do something to maniuplate data
}
void DoSubOperation_B2()
{
// Do something to maniuplate data
}
void DoSubOperation_B3()
{
// Do something to maniuplate data
}
void DoSubOperation_B4()
{
// Do something to maniuplate data
}
int data;
};
You break one big problem into small pieces of problem. You add more
small member functions to class Main. The class Main grows bigger and
bigger.
Too many member functions have different algorithms. You are
confused to choose which member function belongs. They are too
complex to understand.
I decide to group some member functions. How do you group them?
Extract class is the answer. You move some member functions and data
members from class main to another class A and class B.
The class Main *has a* relationship to both class A and class B. I
have one problem. I can’t move data member to another class because
both class A and class B need to access class Main’s data member
directly. I made my decision not to move data member because I allow
both class A and class B manipulate class Main's data member.
I have two options. First option is to place reference argument into
class A class and class B’s member function’s parameter.
Second option is to use friend class and pointer to class Main. The
class Main allows class A and class B’s member functions to access
class Main’s private data member directly.
I choose to use second option instead.
For example:
class Main;
class A
{
public:
A();
~A();
void DoOperation_A();
private:
void SetPointerToMain( Main &_main );
void DoSubOperation_A1();
void DoSubOperation_A2();
void DoSubOperation_A3();
void DoSubOperation_A4();
Main *pMain;
};
class B
{
public:
B();
~B();
void DoOperation_B();
private:
void SetPointerToMain( Main &_main );
void DoSubOperation_B1();
void DoSubOperation_B2();
void DoSubOperation_B3();
void DoSubOperation_B4();
Main *pMain;
};
class Main
{
friend class A;
friend class B;
public:
Main();
~Main();
void Run();
private:
int data;
A a;
B b;
};
A::A() {}
A::~A() {}
void A::SetPointerToMain( Main &_main )
{
pMain = &_main;
}
void A:oOperation_A()
{
DoSubOperation_A1();
DoSubOperation_A2();
DoSubOperation_A3();
DoSubOperation_A4();
}
void A:oSubOperation_A1()
{
// Do something to maniuplate data
pMain->data += 2 * 1;
}
void A:oSubOperation_A2()
{
// Do something to maniuplate data
pMain->data += 2 * 2;
}
void A:oSubOperation_A3()
{
// Do something to maniuplate data
pMain->data += 2 * 3;
}
void A:oSubOperation_A4()
{
// Do something to maniuplate data
pMain->data += 2 * 4;
}
B::B() {}
B::~B() {}
void B::SetPointerToMain( Main &_main )
{
pMain = &_main;
}
void B:oOperation_B()
{
DoSubOperation_B1();
DoSubOperation_B2();
DoSubOperation_B3();
DoSubOperation_B4();
}
void B:oSubOperation_B1()
{
// Do something to maniuplate data
pMain->data += 4 * 1;
}
void B:oSubOperation_B2()
{
// Do something to maniuplate data
pMain->data += 4 * 2;
}
void B:oSubOperation_B3()
{
// Do something to maniuplate data
pMain->data += 4 * 3;
}
void B:oSubOperation_B4()
{
// Do something to maniuplate data
pMain->data += 4 * 4;
}
Main::Main() : data( 0 )
{
a.SetPointerToMain( *this );
b.SetPointerToMain( *this );
}
Main::~Main() {}
void Main::Run()
{
a.DoOperation_A();
b.DoOperation_B();
}
int main()
{
Main m;
m.Run();
printf( "Done." );
return 0;
}
Please let me know if extract method / class is good practice for
readability. Do you have third option?
question how to extract class. I focus to use extract method.
The class Main has one data member. The member function DoOperation_A
() and DoOperation_B() have long methods.
For example:
class Main
{
public:
Main() : data( 0 ) {}
~Main() {}
void DoOperation_A()
{
// Do something to maniuplate data
// Very long method
}
void DoOperation_B()
{
// Do something to maniuplate data
// Very long method
}
private:
int data;
};
I extract DoOperation_A() into four small member functions. I do
extract DoOperation_B() as well. I place them in private. Small
member functions have short methods. They are easier to understand.
They have better readability.
For example:
class Main
{
public:
Main() : data( 0 ) {}
~Main() {}
void DoOperation_A()
{
DoSubOperation_A1();
DoSubOperation_A2();
DoSubOperation_A3();
DoSubOperation_A4();
}
void DoOperation_B()
{
DoSubOperation_B1();
DoSubOperation_B2();
DoSubOperation_B3();
DoSubOperation_B4();
}
private:
void DoSubOperation_A1()
{
// Do something to maniuplate data
}
void DoSubOperation_A2()
{
// Do something to maniuplate data
}
void DoSubOperation_A3()
{
// Do something to maniuplate data
}
void DoSubOperation_A4()
{
// Do something to maniuplate data
}
void DoSubOperation_B1()
{
// Do something to maniuplate data
}
void DoSubOperation_B2()
{
// Do something to maniuplate data
}
void DoSubOperation_B3()
{
// Do something to maniuplate data
}
void DoSubOperation_B4()
{
// Do something to maniuplate data
}
int data;
};
You break one big problem into small pieces of problem. You add more
small member functions to class Main. The class Main grows bigger and
bigger.
Too many member functions have different algorithms. You are
confused to choose which member function belongs. They are too
complex to understand.
I decide to group some member functions. How do you group them?
Extract class is the answer. You move some member functions and data
members from class main to another class A and class B.
The class Main *has a* relationship to both class A and class B. I
have one problem. I can’t move data member to another class because
both class A and class B need to access class Main’s data member
directly. I made my decision not to move data member because I allow
both class A and class B manipulate class Main's data member.
I have two options. First option is to place reference argument into
class A class and class B’s member function’s parameter.
Second option is to use friend class and pointer to class Main. The
class Main allows class A and class B’s member functions to access
class Main’s private data member directly.
I choose to use second option instead.
For example:
class Main;
class A
{
public:
A();
~A();
void DoOperation_A();
private:
void SetPointerToMain( Main &_main );
void DoSubOperation_A1();
void DoSubOperation_A2();
void DoSubOperation_A3();
void DoSubOperation_A4();
Main *pMain;
};
class B
{
public:
B();
~B();
void DoOperation_B();
private:
void SetPointerToMain( Main &_main );
void DoSubOperation_B1();
void DoSubOperation_B2();
void DoSubOperation_B3();
void DoSubOperation_B4();
Main *pMain;
};
class Main
{
friend class A;
friend class B;
public:
Main();
~Main();
void Run();
private:
int data;
A a;
B b;
};
A::A() {}
A::~A() {}
void A::SetPointerToMain( Main &_main )
{
pMain = &_main;
}
void A:oOperation_A()
{
DoSubOperation_A1();
DoSubOperation_A2();
DoSubOperation_A3();
DoSubOperation_A4();
}
void A:oSubOperation_A1()
{
// Do something to maniuplate data
pMain->data += 2 * 1;
}
void A:oSubOperation_A2()
{
// Do something to maniuplate data
pMain->data += 2 * 2;
}
void A:oSubOperation_A3()
{
// Do something to maniuplate data
pMain->data += 2 * 3;
}
void A:oSubOperation_A4()
{
// Do something to maniuplate data
pMain->data += 2 * 4;
}
B::B() {}
B::~B() {}
void B::SetPointerToMain( Main &_main )
{
pMain = &_main;
}
void B:oOperation_B()
{
DoSubOperation_B1();
DoSubOperation_B2();
DoSubOperation_B3();
DoSubOperation_B4();
}
void B:oSubOperation_B1()
{
// Do something to maniuplate data
pMain->data += 4 * 1;
}
void B:oSubOperation_B2()
{
// Do something to maniuplate data
pMain->data += 4 * 2;
}
void B:oSubOperation_B3()
{
// Do something to maniuplate data
pMain->data += 4 * 3;
}
void B:oSubOperation_B4()
{
// Do something to maniuplate data
pMain->data += 4 * 4;
}
Main::Main() : data( 0 )
{
a.SetPointerToMain( *this );
b.SetPointerToMain( *this );
}
Main::~Main() {}
void Main::Run()
{
a.DoOperation_A();
b.DoOperation_B();
}
int main()
{
Main m;
m.Run();
printf( "Done." );
return 0;
}
Please let me know if extract method / class is good practice for
readability. Do you have third option?