Wednesday, January 23, 2019

Harry Potter Kata Written in C#(C Sharp) .net

So I've been looking at some Kata lately and trying to see how they can be approached in different ways.

My initial attempts were pretty poor and didn't have the scalability of testing.

I've since thought about the issues I've tried to address them.

The original Kata can be found on http://codingdojo.org/kata/Potter/

Like with most coding problems you need to take a step back and understand the problem you are trying to solve.

In this case the approach was quite simple, spin up an excel sheet, ensure that we are the results we expect.

So lets look at prices without the discount

for 1 Book the price would be 8
for 2 Books the price would be 16
for 3 Books the price would be 24
for 4 Books the price would be 32
for 5 Books the price would be 40

The with discounts applied:

so in excel we can simply use:
8 * 1 = 0% Discount
16 * 0.95 = 5% Discount
24 * 0.90 = 10% Discount
32 * 0.80 = 20% Discount

Alternative way to work out percentage is (N / 100) * Percentage,

so for example to calculate 5% discount it would be  16 - ((16 / 100) * 5)  = 15.2

for 1 Book the price would be 8
for 2 Books the price would be 15.2
for 3 Books the price would be 21.60
for 4 Books the price would be 25.60
for 5 Books the price would be 30



Our data representation


Ok, so now we have understood the problem, we can look at possible solutions.

I opted for lists of lists, this was to clearly separate the books and make it easier to calculate against.  My original implementation included quantities, but I found this tricky to reduce down and calculate against.  Maybe you know a better way?

If this was to be used on the frontend of a site we could easily cycle through and display the number of books.

I started using XUnit, this is by far better than NUnit and MS Test as it can been extended.  We can use setup coverage tests which allow us to run through several different scenarios.

Below we setup several scenarios in which order to test.  This helps us in several different ways, we can reuse the same test, increase coverage and keep our tests clean.

InlineData will allow us pass through the given parameters for each test as shown below.



So for the next stage we needed to look at the discount mechanism, so how could we know what discount to apply?

Well there are probably a lot of more complex ways to solve this, but sticking to KISS principles I've kept it simple.

Ok, so basically we have a series of cases in a switch statement.  This will allow us to add different logic or discounts as required.  Ideally these would be abstracted away and then created in more flexible generic way for a real application, but for now this fulfills its purpose for this test. 


For the discounts tests, I have made it so we can pass the first parameter to check against the price and the amount of books that we want to test against.  Again we can always go further with these tests and add in mutations, but it proves our code is working as expected for these sequences of books.  Another approach might be to randomise the books in our lists and mix them up.  We could also look at removing specific books systematically then testing again.  

It all boils down to that question "How far do you want to go?" and "Is the code behaving as expected?"


Anyway hopefully this has given you some insights in my though process.  This code is available on GitHub and open to anyone's comments on how this could be made more elegant.

Have Fun and the code can be find in the repo below.

HarryPotterKataV2 Repository

No comments:

Post a Comment