TL;DR After working on the Number Names exercise on Cyber Dojo, I ended up with a fairly comprehensive set of tests for it. I wanted to share my test with others so they could use it to exercise their own implementations. I wanted to make it as easy as possible for them to come up with their own implementations and be able to quickly plug in to my test code with minimal changes on either side. I used the Adapter Pattern to achieve this.
The Question Do you have any other ideas on how I might be able to achieve the goal of pluggability of different implementations without requiring implementations that implement a specific interface? That is, the foreign implementation only needs to take an int as input and return a String as output to be able to get plugged in to this test class.
Skip directly to "The Code" section below if you want to get right down to business.
The Back Story I am a member of an Agile Technical Coach community of practice (CoP) at work and we've been doing exercises in TDD and mob programming. I thought the Number Names exercise would give us plenty of things to study and learn from as coaches and developers. This was one of the problems I got to work on last week during Global Day of CodeRetreat 2021. The link above takes you to where we ended up during GDCR. The road getting there wasn't pretty as you might be able to tell if you go back and look at the different iterations the code went through.
That led me to working on the problem on my own and trying to do Test-Driven Development (TDD) on it. It wasn't pretty either but I got a lot farther than the group did; I actually wrote a complete solution that supported all positive int values and zero, which seemed like one of a few special cases I dealt with. I came up with a recursive solution to the problem.
Others will surely come up with different implementations but I'd like to be able to reuse this test to check their implementations. The API to their solutions are likely going to be different and incompatible with my test though. Forcing other people to extend my own implementation is a bit onerous and puts the burden of making things work with my test on them. That's not going to work well. On the other hand, I don't want to have to change this test significantly just so I can run it against a different implementation.
This is where the Adapter Pattern can help. By having an adapter that can wrap a foreign implementation and adapt its interface to the interface my test expects, I only have to change a single line in the test to use a different implementation.
The Code I'm still tweaking this code but this is what I have at the moment:
So, say for example you had an implementation you decided to call NumberConverter and the method name you settled on was toWords, in order to use your implementation, I'd just have to import your class and change line 31 to:
Even if you decided to use a static method instead of an instance method, I'd still have to only write: