Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  1. In FindHighestNumber project create a new package that ends with .topicmanager

  2. Create a new setup the new test class as shown here (remember you will have errors)

  3. Code Block
    languagec#
    namespace TopicManagerTests
    {
      package xx.yy.zz.topicmanagerservice
    
    public class TopicManagerTests
        {
       
        @Test
      
         public void find_heighest_score_in_empty_array_return_empty_array()
            {
      
             // Arrange
     
              int[] array = {};
                TopicManager cut = new TopicManager();
                int[] expectedResult = {};
    
    
               // Act
       
            Topic[] result = cut.findTopicHighScores(array);
    
      
    
            // Assert
                Assert.That(result, Is.EqualTo(result));
            }
      
     }
    }
  4. Create a new class called TopicManager in the FindHighestNumberService project

  5. Clean the code up so that the class is in a package called TopicManagerService topicmanagerservice

  6. Lines 9, 11, and 14 give us enough information to allow us to start thinking about what we are trying to design here. Based on the requirements, we want to pass into the method findTopicHighScores an array of Topics and their accompanying scores. It should return the top topic score of each Topic, we will call this TopicTopScore. Each item in the array being passed into the findTopicHighScores will be called TopicScores (plural I know, but it matches the context, you may want to lose the ‘s' at the end of the class name). Let’s refactor the code to reflect what we have outlined here.

  7. Code Block
    languagec#
        public class TopicManagerTests
        {
            @Test
            public   void  find_heighest_score_in_empty_array_return_empty_array()
            {
                // Arrange
                ArrayList<TopicScores> array = new ArrayList<>();
                TopicManager cut = new TopicManager();
                ArrayList<TopicTopScore> expectedResult = new ArrayList<>();
          
                // Act
                ArrayList<TopicTopScore> result = cut.findTopicHighScores( array );
          
                // Assert
                assertEquals( expectedResult, result );
            
            }      
        }
  8. We are now in a good position to get VS to generate the findTopicHighScores with the correct signature

  9. Code Block
    languagec#
    class TopicManager
    {
       ArrayList<TopicTopScore> findTopicHighScores(ArrayList<TopicScores> array)
       {
          return new ArrayList<>();
       }
    }
  10. Now we need to complete the first piece of implementation code to pass the test

  11. So you will also need the following pieces of code

  12. Code Block
    package com.s2s.demos.topicmanager;
    
    class Topic
    {
       private  String topicName;
       int      score;
       
       public   Topic( String topicName, int score)
       {
          this.topicName = topicName;
          this.score = score;
       }
    
       public String getTopicName()
       {
          return topicName;
       }
    
       public int getScore()
       {
          return score;
       }
    }
  13. Code Block
    public class TopicTopScore
    {
       
    }
  14. Code Block
    public class TopicScores
    {
       
    }

...

  1. Implement this second test

  2. Code Block
    languagejava
       @Test
       public void find_heighest_score_with_array_of_one_return_array_of_one()
       {
           // Arrange
           int[] scores = { 56, 67, 45, 89 };
           String topicName = "Physics";
           ArrayList<TopicScores> topicScores = new ArrayList<>();
           topicScores.add(new TopicScores(topicName, scores));
       
           TopicManager cut = new TopicManager();
           ArrayList<TopicTopScore> expectedResult = new ArrayList<>();
           expectedResult.add(new TopicTopScore(topicName, 89));
    
           // Act
           ArrayList<TopicTopScore> result = cut.findTopicHighScores(topicScores);
    
           assertEquals(expectedResult.get(0).getTopicName(), result.get(0).getTopicName());
           assertEquals(expectedResult.get(0).getTopScore(), result.get(0).getTopScore() );
       }
  3. And here is the implementation class

  4. Code Block
    languagec#java
    class TopicManager
    {
       private final HighestNumberFinder highestNumberFinder = new HighestNumberFinder();
    
       ArrayList<TopicTopScore> findTopicHighScores(ArrayList<TopicScores> array)
       {
          ArrayList<TopicTopScore> topScores = new ArrayList<>();
    
          if(array.size() == 1)
          {
              TopicScores ts = array.get(0);
              int topScore = highestNumberFinder.findHighestNumber(ts.getScores());
    
              topScores.add(new TopicTopScore(ts.getTopicName(), topScore));
          }
          return topScores;
       }
    }
  5. Updated TopicScores.java

  6. Code Block
    languagejava
    package com.s2s.demos.topicmanager;
    
    public class TopicScores
    {
       private String topicName;
       private int[] scores;
       
       public TopicScores(String topicName, int[] scores)
       {
          this.topicName = topicName;
          this.scores = scores;
       }
       
       public String   getTopicName()
       {
          return topicName;
       }
       
       public   int[] getScores()
       {
          return scores;
       }
    }
  7. Updated TopicTopScores.java

  8. Code Block
    languagejava
    public class TopicTopScore
    {
       private  String topicName;
       private  int topScore;
    
       public TopicTopScore(String topicName, int score)
       {
          this.topScore = score;
          this.topicName = topicName;
       }
       
       public String getTopicName()
       {
          return topicName;
       }
    
       public int getTopScore()
       {
          return topScore;
       }
    }
  9. Looking back at TopicManager, Line 3 represents the elephant in the code

    1. We already have tests for the HighestNumberFinder class, and yes class TopicManager requires HighestNumberFinder. But the coupling between these two classes is such that we cannot test TopicManger independently of HighestNumberFinder. Actually, this is a code smell.

    2. we can not substitute out HighestNumberFinder, this also is a code smell.

    3. We can remove the code smell by injecting HighestNumberFinder into TopicManager, when TopicManager is created.

  10. Modify TopicManager as follows

    1. remove the creation of HighestNumberFinder at line 5

    2. Pass an instance of a HighestNumberFinder into TopicManager as a constructor parameter

  11. Code Block
    languagec#java
    public class TopicManager
    {
        private HighestNumberFinder highestNumberFinder;
    
        public  TopicManager( HighestNumberFinder hnf )
        {
            highestNumberFinder = hnf;
        }
    
        public TopicTopScore[] findTopicHighScores(TopicScores[] array)
        {
            if(array.Length == 1)
            {
                List<TopicTopScore> topScores = new List<TopicTopScore>();
    
                TopicScores ts = array[0];
                int topScore = highestNumberFinder.findHighestNumber(ts.Scores);
    
                topScores.Add(new TopicTopScore(ts.TopicName, topScore));
    
                return topScores.ToArray();
            }
            else
                return Array.Empty<TopicTopScore>();
        }
    }
  12. Refactor the tests so that they run. You should not have to change any of the test data.

...