The use of the adapter really blew my mind! So simple, yet effective. I've been skipping introducing interfaces when not having control of the source code of a class. Thanks!
I know this is a "howto" for mocks. Never the less, it should be at least mentioned, that mocking should be used as last resort. And if the legacy code is large and complex, and it really is THAT hard to extract the methods you wanted to test in to class that only deals with them, you might need to mock. BUT: It should be said, that mocking is a hack! And that the mocking should be intermediate until you get to the point that the code is refactored, cleaned up, and then the mock should be removed and at best replaced with a fake. Why? Because mocking means you are making assumptions about the *implementation* of your *dependency*. And that is a smell of bad design. What you should first try to do, is to clean up the code you want to test and bring it to a state that a mock is not needed (that is, that you do not need to know what is going on in the dependency of your tested code), and that the dependency can be faked instead of being mocked. Fakes are far superior substitutes, exactly because they can do less. If you have a class that has a dependency, it should not care about HOW the dependency is implemented and thus, it would not need to mock. However because there is a dependency, a test can *fake* it, to deliver what ever functionality our class under test is expecting. Mocks are fragile, and bring maintenance cost since they are sensitive to the implementation of the object being mocked. If you have many mocks in your tests, this can become quiet tedious to maintain over time. Also, if the code under tests relies on implementation specifics of what it depends on, it means there is a tight coupling of between them, which again, is a bad design, and a rigid code. I would have loved if this disclaimer would at least have been mentioned.
I really don't like the distinction between mock and fake. I always say "mock" and I really always mean "fake", and I think most people do the same. I don't think many people are mocking in the sense that they try to replicate the dependency logic; that would be insane. The use of a Mock library is basically a shortcut for faking out dependencies; you create the "mock" and set it to return a fake value when called (if needed at all), you don't put any logic into it...
mocking is a code smell. I don't want to spend half or more of my development time maintaining unit tests that have no relation to a user requirement, and add interfaces everywhere just to support tests which makes my code unreadable.
OOP? Assembly? Coding in bits? Edit byte code of physical memory on the machine in a text editor? It's all too high level. Just directly manipulate transistors.
@Smok Good introduction. Looks like what I want. I want to do this with DirectX, which is Microsoft's code and not mine and I can't edit it at all. Adapter pattern it is. That's what I've been thinking. But my code is much more complex than this example and I can't quite get from this video to actually testing my code like this. So I'd like to get a list of connected DirectInput controllers. I can create an adapter to DirectX and methods I'd like to use. And I can create a mock. But how do I make this mock to work? I don't know how exactly DirectInput works. Can you recommend some course or a book which would actually provide realistic examples of how to do this kind of test-driven development when I depend on 3rd-party library? In my case it's DirectX 11 and 12.
Thanks. As to your question: I don't think there is something that would fit your scenario. These are very difficult things, and even this simplified video is a fairly advanced subject. The more "realistic" example you'll pick - the narrower the audience for it (hence it's hard to offer a good advice). Usually these things get hammered out by organisation and their best developers who carve out the rules that others follow. If you don't have anything like that in your org - start one.
The implementation class is not virtual and never will be, you need to create the virtual (abstract) class to serve as the interface. This can be very confusing but the video does explain this quite well. Try to watch it another couple of times and copy his code, play around with it and you will get it.
One more reason for adapter - you don't have to update your code unless it's a breaking change, and even then all you have to update is your adapter. Profit!
The use of the adapter really blew my mind! So simple, yet effective. I've been skipping introducing interfaces when not having control of the source code of a class. Thanks!
And that is the very nature of OOP - spawn a handful of new classes full of boilerplate just to test one thing =)
I know this is a "howto" for mocks.
Never the less, it should be at least mentioned, that mocking should be used as last resort.
And if the legacy code is large and complex, and it really is THAT hard to extract the methods you wanted to test in to class that only deals with them, you might need to mock.
BUT:
It should be said, that mocking is a hack!
And that the mocking should be intermediate until you get to the point that the code is refactored, cleaned up, and then the mock should be removed and at best replaced with a fake.
Why?
Because mocking means you are making assumptions about the *implementation* of your *dependency*.
And that is a smell of bad design.
What you should first try to do, is to clean up the code you want to test and bring it to a state that a mock is not needed (that is, that you do not need to know what is going on in the dependency of your tested code), and that the dependency can be faked instead of being mocked.
Fakes are far superior substitutes, exactly because they can do less.
If you have a class that has a dependency, it should not care about HOW the dependency is implemented and thus, it would not need to mock.
However because there is a dependency, a test can *fake* it, to deliver what ever functionality our class under test is expecting.
Mocks are fragile, and bring maintenance cost since they are sensitive to the implementation of the object being mocked.
If you have many mocks in your tests, this can become quiet tedious to maintain over time.
Also, if the code under tests relies on implementation specifics of what it depends on, it means there is a tight coupling of between them, which again, is a bad design, and a rigid code.
I would have loved if this disclaimer would at least have been mentioned.
I really don't like the distinction between mock and fake. I always say "mock" and I really always mean "fake", and I think most people do the same. I don't think many people are mocking in the sense that they try to replicate the dependency logic; that would be insane.
The use of a Mock library is basically a shortcut for faking out dependencies; you create the "mock" and set it to return a fake value when called (if needed at all), you don't put any logic into it...
mocking is a code smell. I don't want to spend half or more of my development time maintaining unit tests that have no relation to a user requirement, and add interfaces everywhere just to support tests which makes my code unreadable.
Nice video, really helps me as a newbie to testing.
Great video! So after introducing the interface the LegacyClass can return to the original non-virtual functions, right?
Great explanation! Helped me a lot, thanks Smoku!
What IDE do you use?
Great video, but really reminds me why I hate oop
Yeah it's hard. But if you're in constrained environment - this is way better than plain C
we all love assembly, don't we? I'd like to code in bits directly... but you know... I'm such _a high class man_ ( ͡° ͜ʖ ͡°)
OOP? Assembly? Coding in bits? Edit byte code of physical memory on the machine in a text editor? It's all too high level. Just directly manipulate transistors.
you should better mention that after adding the interface, we need to modify TEST too and pass the LegacyClass into TestUnit.
PIMPL is an underrated idiom. I replaced so many switch cases with pointer to functions and classes. Pointer to class::member is also kinda of PIMPL
@Smok Good introduction. Looks like what I want. I want to do this with DirectX, which is Microsoft's code and not mine and I can't edit it at all. Adapter pattern it is. That's what I've been thinking. But my code is much more complex than this example and I can't quite get from this video to actually testing my code like this. So I'd like to get a list of connected DirectInput controllers. I can create an adapter to DirectX and methods I'd like to use. And I can create a mock. But how do I make this mock to work? I don't know how exactly DirectInput works.
Can you recommend some course or a book which would actually provide realistic examples of how to do this kind of test-driven development when I depend on 3rd-party library? In my case it's DirectX 11 and 12.
Thanks. As to your question: I don't think there is something that would fit your scenario. These are very difficult things, and even this simplified video is a fairly advanced subject. The more "realistic" example you'll pick - the narrower the audience for it (hence it's hard to offer a good advice). Usually these things get hammered out by organisation and their best developers who carve out the rules that others follow. If you don't have anything like that in your org - start one.
What team in amazon do you work for ? I believe that most team uses Java
This is great but what if the class is not virtual? Declare it as virtual with some macros for testing?
The implementation class is not virtual and never will be, you need to create the virtual (abstract) class to serve as the interface. This can be very confusing but the video does explain this quite well. Try to watch it another couple of times and copy his code, play around with it and you will get it.
How do I view PPT files on the website using the Django framework?
Hey Smok, Can you share the project somewhere ?
thank you, useful video
what editor is that?
CLion from JetBrains
Genius!
Very nice video! Well explained!
But what if legacy class gets updated?
One more reason for adapter - you don't have to update your code unless it's a breaking change, and even then all you have to update is your adapter. Profit!
Thanks for this. What are those UML cards made of?
Most of them are recycled from bad ideas and hours wasted on debugging.
@@SmokCode lol but what material? Looks more thick/rigid than paper
yup, photo paper glued with two layers of thick 160g satin paper
@@SmokCode Thanks : ) They look nice. Good for video props.
wow
Your engliah is the best. Great you.
Most stupid idea. If the class is "legacy" it most likely means that you can't make its methods virtual.
Did you watch the entire video, or stopped when he mentioned that solution? The adapter would solve that issue.
Why are you so bitter?
@@Smartskaft2 exactly; maybe the video content could use some reorganising
@@ignacionr your comments could use some deletion