Code Kata 2 Day 5, The One with the Async

So to complete Code Kata 2, I have decided to try and build a asynchronous implementation. Honestly, my multi-threading is not as good as it should. I generally try to avoid it but in 2020, I have decided to take my medicine and start doing it everyone it is reasonable to do it. So in past programs as I do new features, I am, for free, adjusting the code to be asynchronous. So far, I don’t think there has been awareness of it but it feels good to improve in a real way, older code bases I have worked on. Get ready for Code Kata 2 Day 5.

In the spirit of this, I am going to try it here. You have been warned, this is not likely to be pretty.

Wow, you are really talking yourself up today. Keep this up and you will be on the streets begging for money from your Friends.

There is my lovable snark from my blogging aid. I do appreciate that my joke did not fall on deaf ears. I wonder if anyone else got it. Let’s stop this dialog and get to showing off the code.

Day5Chop.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace CodeKata2
{
   public class Day5Chop
   {
      public int chop(int numberToSeek, List intList)
      {
          int result; 
         result = getNumber(numberToSeek,intList).Result; 
         return result; 
      } 

      private async Task<int> getNumber(int numberToSeek, List<int> intList) 
      { 
         int result = -1; 
         int result1; 
         int result2; 
         int counter = 0; 
         Dictionary<int, int> int1 = new Dictionary<int, int>(); 
         Dictionary<int, int> int2 = new Dictionary<int, int>(); 
   
         while (counter < intList.Count) 
         { 
            if(counter % 2 == 0) 
            { 
               int1.Add(counter, intList[counter]); 
            } 
            else 
            { 
               int2.Add(counter, intList[counter]); 
            } 
            counter++; 
         } 
         
         result1 = await getData(int1, numberToSeek).ConfigureAwait(false); 
         result2 = await getData(int2, numberToSeek); 

         if(result1 == -1) 
         { 
            result = result2; 
         } 
         else 
         { 
            result = result1; 
         } 
 
         return result; 
      } 

      private Task<int> getData(Dictionary<int,int> list, int numberToSeek) 
      { 
         return Task.Factory.StartNew(() => 
         { 
            return findNumber(list, numberToSeek); 
         }); 
      } 

      private int findNumber(Dictionary<int, int> list, int numberToSeek) 
      { 
         int result = -1; 
         foreach(var i in list) 
         { 
            if(numberToSeek == i.Value) 
            { 
               return i.Key; 
            } 
          } 
          return result; 
       } 
   }
}

Breakdown of Code Kata 2 Day 5’s solution

My first constraint was to not mess with the signature of the function. I have read several things over the years arguing that it is not changing the signature by adding a async. I think it does. Besides, in this case it would because of the async constraints. We are returning type int and that is not a Task<T> nor a void.

As a result, I set the chop function up pretty straight. Just get the number and return the number. I should refactor this to just return the function’s result but none of the kata have been that refined.

So the chop calls the getNumber function and passes the same parameter list. There was no reason for the parameter flip, other then the order that I thought of them. I would probably flip them in a refactor.

getNumber

So this is the function where we get to the async, await world. First, I break the single data set into two. I use a dictionary to keep track of the real index in the original list. You might remember this from one of my previous attempts.

Next I call the getData function to call a task that will call the function that actually determines the comparison.

When I tried the first time, I got a condition where my unit test passed but my integration test failed. Then my code stopped on the first await. I believe it was caused by a deadlock. So I added the ConfigureAwait(false) and everything went back to normal. I am not sure I did not just blow up my multi-thread attempt by doing it. I am still a little confused.

Anyway the results are compared and anything that is not a -1 gets returned, otherwise -1 gets returned.

Finally the getData function starts a new task that returns and integer from the findNumber function which just checks the list for the number and returns the key value from the dictionary. As you hopefully recall, this was the original index number.

So you have no idea of what you are doing?

I did not say that. I just said that I did really know if my solution messed up my multi-threading. The old async muscles are underdeveloped and I am still getting my reps in on this and I am not very good at it. Granted it has been around for years, but most of the code bases where of the background worker era. I am just now trying to bring everything up to date and that includes me.

There are at least half a dozen best practices I violated or so I assume, so please let me know where I messed up. It is always good to have people smarter than me to do some educating. I hate to end this part of the series with Code Kata 2 Day 5 Revenge of the Suck Code. Atlas that is what I am doing.

So this wraps up Code Kata 2. Hopefully Code Kata 3 will not take a week to do. I really enjoyed the coding part since the first one let me down on the coding part.

Leave a Reply

Your email address will not be published.