working with c++ legacy code
TRANSCRIPT
![Page 2: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/2.jpg)
Consultant @CodeValue
Developing software since 2002Clean Coder & Test Driven Developer
Pluralsight authorhttps://www.pluralsight.com/authors/dror-helper
B: http://helpercode.comT: @dhelper
About.ME
![Page 3: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/3.jpg)
¯\_(ツ)_/¯What is “Legacy Code”?
Covfefe?
![Page 4: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/4.jpg)
No longer engineered – continuedly patched
![Page 5: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/5.jpg)
Difficult to change without breaking functionality
![Page 6: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/6.jpg)
Written by someone else
![Page 7: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/7.jpg)
Legacy code has users!
![Page 8: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/8.jpg)
The good news and bad news
There’s a lot of legacy C++ Code
There’s a good chance you’re doing it
C++ makes it easy to make critical mistakes
C++ is a powerful language
![Page 9: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/9.jpg)
Gaining control over legacy code
To stop fearing legacy code:
1. Learn what the code does
2. Make sure it keeps doing it!
3. Iterative improvement via Refactoring
![Page 10: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/10.jpg)
This is a unit test (GTest)
TEST(HolyGrailTests, WhoWeAreTest)
{
Knight knight;
ASSERT_EQ(“Ni!”, knight.Say());
}
![Page 11: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/11.jpg)
A quick reality check
• Code have dependencies
• Refactoring == code change
• Code change == breaking functionality (78.3%)
• Breaking functionality go home == false
![Page 12: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/12.jpg)
Sensing and Separation
public void SendEmailTest(){
auto sut = new ...User user;sut->SendEmailToUser(user);
// Sensing problemASSERT???
}
void SendEmailToUser(User user){
EmailClient client;
// Separation problemclient.Send(user.Email, ...);
// Important business logic...
}
![Page 13: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/13.jpg)
“My focus is to forget the pain of life. Forget the pain, mock the pain, reduce it. And laugh.” Jim Carrey
![Page 14: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/14.jpg)
The problem - dependencies
My Code
DB
FilesFiles
FilesFiles
Services
![Page 15: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/15.jpg)
The solution – fake/mock objects
My Code
Fake
Fake
Fake
![Page 16: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/16.jpg)
Fake objects using Google Mock
class FakeRestApiClient : public RestApiClient
{
public:
MOCK_METHOD2(HttpPost, void(string&, string&));
MOCK_METHOD1(HttpGet, string(string&));
MOCK_METHOD2(HttpPut, void(string&, string&));
MOCK_METHOD1(HttpDelete, void(string&));
};
![Page 17: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/17.jpg)
Injecting fake objects into existing code
![Page 18: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/18.jpg)
Not all dependency are created equal
Some are harder/impossible to fake
Non virtual methods
Hard to inherit classes
Static method
callsSingletons
Internally instantiated
Heavy classes
![Page 19: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/19.jpg)
Faking Singletons
class MySingleton {
static std::once_flag onceFlag;static MySingleton* instance;
public:static MySingleton* GetInstance() {
std::call_once(onceFlag, [] {instance = new MySingleton();
});
return instance;}
private:
MySingleton(){}
}
![Page 20: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/20.jpg)
Friend is your friend
class MySingletons;
class Rectangle
{
int width, height;
public:
friend FakeRectangle;
};
![Page 21: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/21.jpg)
Problem: un-fakeable methods
• Static methods
• Hard/impossible to instantiate class
• Non-virtual methods
Cannot be inherited == cannot be injected!
![Page 22: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/22.jpg)
Using templates for injection
Compile time duck typing a.k.a hi-perf dependency injection
• Can fake unfakeables
• Can fake internally instantiated classes
![Page 23: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/23.jpg)
Faking Private and Protected Methods
class Foo
{
public:
virtual bool MyPublicMethod(MyClass* c){...};
protected:
virtual void MyProtectedMethod(int a, int b){...};
private:
virtual int MyPrivateMethod(){...}
}
![Page 24: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/24.jpg)
Faking Private and Protected Methods
class Foo
{
public:
MOCK_METHOD1(MyPublicMethod, bool(MyClass*));
MOCK_METHOD2(MyProtectedMethod, void(int, int));
MOCK_METHOD0(MyPrivateMethod, int());
}
![Page 25: Working with c++ legacy code](https://reader031.vdocuments.site/reader031/viewer/2022021815/5a64ad8d7f8b9a94568b5157/html5/thumbnails/25.jpg)
Taking control of existing legacy code
Legacy code
Write testsCreate fake
objects
Swap dependencies
Refactor & cleanup
Maintainable code