...

/

The SRP and Profile class

The SRP and Profile class

Learn the importance and implementation of the Single Responsibility Principle (SRP) in profile class.

Writing unit tests isn’t an exercise that occurs in a vacuum. It’s instead part of the larger, continually shifting puzzle we call design. Our system’s design impacts our ability to write tests and vice versa.

We’ll also investigate command-query separation, which uses methods that don’t end up fooling their users by both creating side effects and returning values.

We’ll apply these principles by refactoring code in the Profile class.

Let’s take a look at our Profile class so far:

package iloveyouboss;

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

public class Profile {
   private Map<String,Answer> answers = new HashMap<>();

   private int score;
   private String name;

   public Profile(String name) {
      this.name = name;
   }
   
   public String getName() {
      return name;
   }

   public void add(Answer answer) {
      answers.put(answer.getQuestionText(), answer);
   }

   public boolean matches(Criteria criteria) {
      calculateScore(criteria);
      if (doesNotMeetAnyMustMatchCriterion(criteria))
         return false;
      return anyMatches(criteria);
   }

   private boolean doesNotMeetAnyMustMatchCriterion(Criteria criteria) {
      for (Criterion criterion: criteria) {
         boolean match = criterion.matches(answerMatching(criterion));
         if (!match && criterion.getWeight() == Weight.MustMatch) 
            return true;
      }
      return false;
   }

   private void calculateScore(Criteria criteria) {
      score = 0;
      for (Criterion criterion: criteria) 
         if (criterion.matches(answerMatching(criterion))) 
            score += criterion.getWeight().getValue();
   }

   private boolean anyMatches(Criteria criteria) {
      boolean anyMatches = false;
      for (Criterion criterion: criteria) 
         anyMatches |= criterion.matches(answerMatching(criterion));
      return anyMatches;
   }

   private Answer answerMatching(Criterion criterion) {
      return answers.get(criterion.getAnswer().getQuestionText());
   }

   public int score() {
      return score;
   }

   public List<Answer> classicFind(Predicate<Answer> pred) {
      List<Answer> results = new ArrayList<Answer>();
      for (Answer answer: answers.values())
         if (pred.test(answer))
            results.add(answer);
      return results;
   }
   
   @Override
   public String toString() {
     return name;
   }

   public List<Answer> find(Predicate<Answer> pred) {
      return answers.values().stream()
            .filter(pred)
            .collect(Collectors.toList());
   }
}
Testing modified Profile class

Example: Profile class and SRP

At under a hundred source lines, Profile isn’t inordinately large and doesn’t seem excessively complex. It does contain some hints that the class exhibits less-than-ideal design, though.

  • The Profile class tracks and manages information for a company or person, including a name and a collection of answers to questions. This set of information that the Profile class captures will most likely need to change over time. More information will ...

Access this course and 1400+ top-rated courses and projects.