Mark Oliver's World

Posted: 10/04/2021

Job Search 2021 _ Another Programming Test

I have already spoken about my issue with programming tests for interview, and again, in order to get an interview, I have completed one by treating it as a learning exercise.
This time to practice TDD on a legacy application.
Can I still write a comprehensive test suite for an untestable app then refactor it bit by bit making it more testable at each stage.

This interview test was to take an existing console app and make it better.

It was a simple coffee shop idea, you enter in the customers who buy drinks throughout the day, and then can print a summary of the trading.

The code is messy and has a few bugs, it also is not following SOLID principles or Clean code ideas.

The test was 3 fold:

  • Write tests
  • Tidy code to make it. More maintainable
  • Add some new features.

Oddly the code is delivered via zip file and that's how it is returned too. I guess this is to reduce the number of copies turning up on github, thus making it easy for others to pass the test. So first thing I did was put it in a private github repo! 😃

Then I could start working on the problem set.

First was to read the code and run the app to see what it did.

After experimenting with the program and a quick run through of the code, I thought I should upgrade it to dotnet 5!
This was REALLY easy using the dotnet upgrade assistant it did all the work for me.
I proved everything was still working after the upgrade manually.
However now it is in dotnet 5 ( it was in framework before), its much easier to work with!

Then I wrote tests for the public api of the main logic class.
The app is just 2 main classes. 1 to interpret user input, and the other to run the coffee shop logic.
So focusing on the coffee shop api, I test its two entry points.

  • Add a customer
  • Print out report

Because the code is all executed through these 2 places, the tests have to be very high level.

Once these were in place however I can do some more housekeeping.

  • Add github pipeline to build and test
  • Split big methods down to smaller ones but. Maintaining the existing public api and not adding classes. Basically making it more readable.

The tests still pass woohoo.

Now let's look at that coffee shop class. It has 3 responsibilities.

  • Maintain list of customers and what drink is being sold
  • Calculate the statistics of the shop e.g. The summary of number of customers, drinks and operating costs.
  • Print a summary.

I decided to focus on the statistics first. Split that out to a separate class and test it separately.

One this was done, it was time to tackle the new feature requests.

  • A new customer type
  • A change to billing rules for existing customer type
  • A new shop requirement

These were each tackled independently and tested. Refactoring the code as each feature was approached.

At this point I am done with 2 of the 3 requirements. It's tested, new features added, and it's also maintainable now. However the remit was to make it maintainable using clean code ideas, so now it's time to look at the code once again and apply those principles, Solid, kiss, dry etc...

I spent a lot of time on this for the recruitment, primarily because it was enjoyable, but also I want the job!

However in hindsight, I wonder should i have tackled it differently?
I wanted to always commit working code, so it meant having tests in place, and nothing broken every time.
This in itself though made me focus on small things each time.
Perhaps if I had taken a big bang approach to it I would have come up with something even "cleaner".

For now though, I stick by my approach. probably more than 95% of the 56 commits I made for this small app were with a completely working system, that could have been delivered to the end user at any point. In my mind this is incredibly important when dealing with Legacy code!


Thanks for reading this post.

If you want to reach out, catch me on Twitter!

I am always open to mentoring people, so get in touch.