SlideShare a Scribd company logo
The First 100 Hours:
 Commonality and
 Variability Analysis

Jason Cheong-Kee-You
  @jpcky www.mightyjupiter.com


   Alistair McKinnell
@amckinnell www.valuablecode.com
Commonality and
Variability Analysis
Commonality and
   Variability Analysis

Avoiding Duplicate Code
Exercise
Exercise
1. Did you write any code last year?
   If so, how many lines of code?
2. How many lines of code in your
   code base?
3. Percentage of duplicate code?
Code Visibility
Code Visibility
Code Visibility
Avoiding Duplicate Code
Avoiding Duplicate Code
Avoiding Duplicate Code

     DRY: Don’t Repeat Yourself
Avoiding Duplicate Code

     DRY: Don’t Repeat Yourself
     Every piece of knowledge must have
     a single, unambiguous, authoritative
     representation within a system.
Avoiding Duplicate Code
Avoiding Duplicate Code

     Once and Only Once
Avoiding Duplicate Code

     Once and Only Once
     Data, structure, or logic should exist
     in only one place in the system.
Avoiding Duplicate Code
Avoiding Duplicate Code

     Test-Driven Development
Avoiding Duplicate Code

     Test-Driven Development
     1. Write new code only if an
        automated test has failed.
Avoiding Duplicate Code

     Test-Driven Development
     1. Write new code only if an
        automated test has failed.
     2. Eliminate duplication.
Avoiding Duplicate Code
Avoiding Duplicate Code

     Single Choice Principle
Avoiding Duplicate Code

     Single Choice Principle
     Whenever a software system must
     support a set of alternatives, one
     and only one module in the system
     should know their exhaustive list.
Avoiding Duplicate Code
Avoiding Duplicate Code

     Duplication may be the
     root of all evil in software.
Exercise
Exercise
Exercise

What are the consequences of
duplicate code?
Exercise

What are the consequences of
duplicate code?


Consider both good and evil.
Exercise
Exercise
Exercise

How does duplicate code
come about?
Exercise

How does duplicate code
come about?


Make a Top 3 list.
Commonality and Variability Analysis: Avoiding Duplicate Code
Alistair’s Contention
Alistair’s Contention
Copy and Paste leads to the
creation of duplicate code.
Alistair’s Contention
Copy and Paste leads to the
creation of duplicate code.
Developers lack the thinking tools
and the development skills to avoid
the duplication.
Duplicate Code:
Select Options
Select Options
public static List<SelectOption> createEndMonthList(Date expiryDate) {
    List<SelectOption> monthList = new ArrayList<SelectOption>();
    int month = getDateMonth(expiryDate);
    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(true);
        } else {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(false);
        }
        monthList.add(option);
    }
    return monthList;
}
Select Options
public static List<SelectOption> createEndMonthList(Date expiryDate) {
    List<SelectOption> monthList = new ArrayList<SelectOption>();
    int month = getDateMonth(expiryDate);
    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(true);
        } else {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(false);
        }
        monthList.add(option);
    }
    return monthList;
}
Select Options
public static List<SelectOption> createEndMonthList(Date expiryDate) {
    List<SelectOption> monthList = new ArrayList<SelectOption>();
    int month = getDateMonth(expiryDate);
    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(true);
        } else {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(false);
        }
        monthList.add(option);
    }
    return monthList;
}
Select Options
public static List<SelectOption> createEndMonthList(Date expiryDate) {
    List<SelectOption> monthList = new ArrayList<SelectOption>();
    int month = getDateMonth(expiryDate);
    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(true);
        } else {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(false);
        }
        monthList.add(option);
    }
    return monthList;
}
Select Options
public static List<SelectOption> createEndMonthList(Date expiryDate) {
    List<SelectOption> monthList = new ArrayList<SelectOption>();
    int month = getDateMonth(expiryDate);
    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(true);
        } else {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(false);
        }
        monthList.add(option);
    }
    return monthList;
}
Select Options
public static List<SelectOption> createEndMonthList(Date expiryDate) {
    List<SelectOption> monthList = new ArrayList<SelectOption>();
    int month = getDateMonth(expiryDate);
    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(true);
        } else {
            option.setLabel(String.valueOf(intLooper));
            option.setValue(String.valueOf(intLooper));
            option.setSelected(false);
        }
        monthList.add(option);
    }
    return monthList;
}
Select Options
           SelectOptions                       SelectOptionsSource

create()                                   getFirst()
                                           getLast()
                                           isSelected()




    Commonality              Variability                  Resolution

   Data Structure          Value of State            Simple Java Type
Select Options
           SelectOptions               SelectOptionsSource

create()                          getFirst()
                                  getLast()
                                  isSelected()




                           Parameter
                           Object
Select Options
           SelectOptions                      SelectOptionsSource

create()                                  getFirst()
                                          getLast()
                                          isSelected()




    Commonality             Variability                  Resolution
                                                         Encapsulate
       Behaviour           Collaborator
                                                         Collection
Select Options
           SelectOptions               SelectOptionsSource

create()                           getFirst()
                                   getLast()
                                   isSelected()




                           Encapsulate
                           Collection
Duplicate Code:
Select Options Extra
Select Options Extra
public static List<SelectOption> createProvinceList(String selectedProvince)
{
    List<SelectOption> provinceList = new ArrayList<SelectOption>();

    List<String> provinces = asList("AB", "BC", "MB", "NB", "NL",
            "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT");

    for (int intLooper = 0; intLooper < provinces.size(); intLooper++) {
        SelectOption option = new SelectOption();
        if (selectedProvince.equals(provinces.get(intLooper))) {
        option.setLabel(provinces.get(intLooper));
            option.setValue(provinces.get(intLooper));
            option.setSelected(true);
        } else {
            option.setLabel(provinces.get(intLooper));
            option.setValue(provinces.get(intLooper));
            option.setSelected(false);
        }
        provinceList.add(option);
    }
    return provinceList;
}
Select Options Extra
public static List<SelectOption> createProvinceList(String selectedProvince)
{
    List<SelectOption> provinceList = new ArrayList<SelectOption>();

    List<String> provinces = asList("AB", "BC", "MB", "NB", "NL",
            "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT");

    for (int intLooper = 0; intLooper < provinces.size(); intLooper++) {
        SelectOption option = new SelectOption();
        if (selectedProvince.equals(provinces.get(intLooper))) {
        option.setLabel(provinces.get(intLooper));
            option.setValue(provinces.get(intLooper));
            option.setSelected(true);
        } else {
            option.setLabel(provinces.get(intLooper));
            option.setValue(provinces.get(intLooper));
            option.setSelected(false);
        }
        provinceList.add(option);
    }
    return provinceList;
}
Select Options Extra
List<String> provinces = asList("AB", "BC", "MB", "NB", "NL",
            "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT");
Select Options Extra
List<String> provinces = asList("AB", "BC", "MB", "NB", "NL",
            "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT");



public enum Province {
    AB, BC, MB, NB, NL, NT, NS, NU, ON, PE, QC, SK, YT;
}




      Commonality                Variability              Resolution
                              A small set of
     Data Structure                                         enum
                                 values
Select Options Extra
public enum Province {
    AB, BC, MB, NB, NL, NT, NS, NU, ON, PE, QC, SK, YT;
}




                    Single Choice Principle
                    Whenever a software system must
                    support a set of alternatives, one
                    and only one module in the system
                    should know their exhaustive list.
Select Options Extra
public static List<SelectOption> createEndMonthList(Date expiryDate) {

    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));

}

public static List<SelectOption> createProvinceList(String selectedProvince)
{

    for (int intLooper = 0; intLooper < provinces.size(); intLooper++) {
        SelectOption option = new SelectOption();
        if (selectedProvince.equals(provinces.get(intLooper))) {
            option.setLabel(provinces.get(intLooper));


}
Select Options Extra
public static List<SelectOption> createEndMonthList(Date expiryDate) {

    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));

}

public static List<SelectOption> createProvinceList(String selectedProvince)
{

    for (int intLooper = 0; intLooper < provinces.size(); intLooper++) {
        SelectOption option = new SelectOption();
        if (selectedProvince.equals(provinces.get(intLooper))) {
            option.setLabel(provinces.get(intLooper));


}
Select Options Extra
public static List<SelectOption> createEndMonthList(Date expiryDate) {

    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));

}

public static List<SelectOption> createProvinceList(String selectedProvince)
{

    for (int intLooper = 0; intLooper < provinces.size(); intLooper++) {
        SelectOption option = new SelectOption();
        if (selectedProvince.equals(provinces.get(intLooper))) {
            option.setLabel(provinces.get(intLooper));


}
Select Options Extra
public static List<SelectOption> createEndMonthList(Date expiryDate) {

    for (int intLooper = 1; intLooper <= 12; intLooper++) {
        SelectOption option = new SelectOption();
        if (month == intLooper) {
            option.setLabel(String.valueOf(intLooper));

}

public static List<SelectOption> createProvinceList(String selectedProvince)
{

    for (int intLooper = 0; intLooper < provinces.size(); intLooper++) {
        SelectOption option = new SelectOption();
        if (selectedProvince.equals(provinces.get(intLooper))) {
            option.setLabel(provinces.get(intLooper));


}
Select Options Extra
                                                                      String
                                                           Iterable

                                                   iterator()




            SelectOptions                       SelectOptionsSource

 create()                                   isSelected()




                                 IntegerRangeSource                            ProvinceSource

                            iterator()                                iterator()
                            isSelected()                              isSelected()
Select Options Extra
                                                                      String
                                                           Iterable

                                                   iterator()




            SelectOptions                       SelectOptionsSource

 create()                                   isSelected()




                                 IntegerRangeSource                            ProvinceSource

                            iterator()                                iterator()
                            isSelected()                              isSelected()
Select Options Extra
                                                                           String
                                                                Iterable

                                                        iterator()




                 SelectOptions                       SelectOptionsSource

      create()                                   isSelected()




                                      IntegerRangeSource                            ProvinceSource

                                 iterator()                                iterator()
                                 isSelected()                              isSelected()




Commonality                               Variability                                          Resolution

 Collection                                     Values                                               Iterator
Select Options Extra
                                                                           String
                                                                Iterable

                                                        iterator()




                 SelectOptions                       SelectOptionsSource

      create()                                   isSelected()




                                      IntegerRangeSource                            ProvinceSource

                                 iterator()                                iterator()
                                 isSelected()                              isSelected()




Commonality                               Variability                                          Resolution

 Collection                                     Type                                             Generics
Select Options Extra
                                                                          String
                                                               Iterable

                                                       iterator()




                SelectOptions                       SelectOptionsSource

     create()                                   isSelected()




                                     IntegerRangeSource                            ProvinceSource

                                iterator()                                iterator()
                                isSelected()                              isSelected()




Commonality                              Variability                                          Resolution
                                                                                        Inheritance
 Behaviour                       Implementation
                                                                                     (Object-Oriented)
Duplicate Code:
Compound Result Handler
Compound Result Handler
public Collection<IRegCommand> processCompondResults(Patient sourcePatient, Collection<Result> results) {
    Collection<IRegCommand> retVal = new ArrayList<IRegCommand>();
    Set<Result> resultsMarkedForRemoval = new HashSet<Result>();
    Set<Result> resultsProcessed = new HashSet<Result>();

    for (Result primaryResult : results) {
        if (isResultProcessed(resultsProcessed, primaryResult)) {
            continue;
        }

        resultsProcessed.add(primaryResult);
        Result correspondingResult = getCorrespondingResult(primaryResult, results);

        if (correspondingResult != null) {
            resultsProcessed.add(correspondingResult);
            resultsMarkedForRemoval.add(correspondingResult);
        }

        if (!sourcePatient.getDataWarehouse().equals(DataWarehouseTag.QHN)) {
            // If the response to either question is yes then display positive as the measure value.
            if (primaryResult.getDwValue().equalsIgnoreCase("1")) {
                 primaryResult.setDwValue("POSITIVE");
            } else {
                 // If the response to both questions is no then display negative as the measure value.
                 if (correspondingResult != null) {
                     if (correspondingResult.getDwValue().equalsIgnoreCase("2")) {
                          primaryResult.setDwValue("NEGATIVE");
                     } else if (correspondingResult.getDwValue().equalsIgnoreCase("1")) {
                          // It must be yes - thus value is POSITIVE
                          primaryResult.setDwValue("POSITIVE");
                     } else {
                          badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                                  primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                                  "Issue with multiple PHQ results");
                          continue;
                     }
                 } else {
                     // No corresponding result - where is the 2nd result? -
                     badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                              primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                              "No corresponding value found for a 2 item screener with value of 'no'");
                     continue;
                 }
            }
        } else {
            // If the response to either question is yes then display positive as the measure value.
            if (primaryResult.getDwValue().equalsIgnoreCase("3") ||
                              primaryResult.getDwValue().equalsIgnoreCase("4")) {
                 primaryResult.setDwValue("POSITIVE");
            } else {
                 // If the response to both questions is no then display negative as the measure value.
                 if (correspondingResult != null) {
                     if (primaryResult.getDwValue().equalsIgnoreCase("0") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("1") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("2")) {
                          primaryResult.setDwValue("NEGATIVE");
                     } else if (primaryResult.getDwValue().equalsIgnoreCase("3") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("4")) {
                          // It must be yes - thus value is POSITIVE
                          primaryResult.setDwValue("POSITIVE");
                     } else {
                          badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                                  primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                                  "Issue with multiple PHQ results");
                          continue;
                     }
                 } else {
                     // No corresponding result - where is the 2nd result? -
                     badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                              primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                              "No corresponding value found for a 2 item screener with value of 'no'");
                     continue;
                 }
            }
        }

        Map<String, Object> transformedResult = resultTransformer.transformResult(sourcePatient, primaryResult);

        if (null != transformedResult) {
            retVal.add(new PatientDataUpdateCommand(CommandType.RESULT, sourcePatient, transformedResult));
        }
    }

    return retVal;
}
Compound Result Handler
public Collection<IRegCommand> processCompondResults(Patient sourcePatient, Collection<Result> results) {
    Collection<IRegCommand> retVal = new ArrayList<IRegCommand>();
    Set<Result> resultsMarkedForRemoval = new HashSet<Result>();
    Set<Result> resultsProcessed = new HashSet<Result>();

    for (Result primaryResult : results) {
        if (isResultProcessed(resultsProcessed, primaryResult)) {
            continue;
        }

        resultsProcessed.add(primaryResult);
        Result correspondingResult = getCorrespondingResult(primaryResult, results);

        if (correspondingResult != null) {
            resultsProcessed.add(correspondingResult);

        }
            resultsMarkedForRemoval.add(correspondingResult);
                                                                                                                   if (!sourcePatient.getDataWarehouse()
        if (!sourcePatient.getDataWarehouse().equals(DataWarehouseTag.QHN)) {
            // If the response to either question is yes then display positive as the measure value.
            if (primaryResult.getDwValue().equalsIgnoreCase("1")) {
                 primaryResult.setDwValue("POSITIVE");
                                                                                                                           .equals(DataWarehouseTag.QHN)) {
            } else {
                 // If the response to both questions is no then display negative as the measure value.
                 if (correspondingResult != null) {
                     if (correspondingResult.getDwValue().equalsIgnoreCase("2")) {
                          primaryResult.setDwValue("NEGATIVE");
                     } else if (correspondingResult.getDwValue().equalsIgnoreCase("1")) {
                          // It must be yes - thus value is POSITIVE
                          primaryResult.setDwValue("POSITIVE");
                     } else {
                          badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                                  primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                                  "Issue with multiple PHQ results");
                          continue;
                     }
                 } else {
                     // No corresponding result - where is the 2nd result? -
                     badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                              primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                              "No corresponding value found for a 2 item screener with value of 'no'");
                     continue;
                 }
            }
        } else {
            // If the response to either question is yes then display positive as the measure value.
            if (primaryResult.getDwValue().equalsIgnoreCase("3") ||
                              primaryResult.getDwValue().equalsIgnoreCase("4")) {
                 primaryResult.setDwValue("POSITIVE");
            } else {
                 // If the response to both questions is no then display negative as the measure value.
                 if (correspondingResult != null) {
                     if (primaryResult.getDwValue().equalsIgnoreCase("0") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("1") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("2")) {
                          primaryResult.setDwValue("NEGATIVE");
                     } else if (primaryResult.getDwValue().equalsIgnoreCase("3") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("4")) {
                          // It must be yes - thus value is POSITIVE
                          primaryResult.setDwValue("POSITIVE");
                     } else {
                          badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                                  primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                                  "Issue with multiple PHQ results");
                          continue;
                     }
                 } else {
                     // No corresponding result - where is the 2nd result? -
                     badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                              primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                              "No corresponding value found for a 2 item screener with value of 'no'");
                     continue;
                 }
            }
        }

        Map<String, Object> transformedResult = resultTransformer.transformResult(sourcePatient, primaryResult);

        if (null != transformedResult) {
            retVal.add(new PatientDataUpdateCommand(CommandType.RESULT, sourcePatient, transformedResult));
        }
    }

    return retVal;
}
Compound Result Handler
public Collection<IRegCommand> processCompondResults(Patient sourcePatient, Collection<Result> results) {
    Collection<IRegCommand> retVal = new ArrayList<IRegCommand>();
    Set<Result> resultsMarkedForRemoval = new HashSet<Result>();
    Set<Result> resultsProcessed = new HashSet<Result>();

    for (Result primaryResult : results) {
        if (isResultProcessed(resultsProcessed, primaryResult)) {
            continue;
        }

        resultsProcessed.add(primaryResult);
        Result correspondingResult = getCorrespondingResult(primaryResult, results);

        if (correspondingResult != null) {
            resultsProcessed.add(correspondingResult);

        }
            resultsMarkedForRemoval.add(correspondingResult);


        if (!sourcePatient.getDataWarehouse().equals(DataWarehouseTag.QHN)) {
                                                                                                   if (primaryResult.getDwValue().equalsIgnoreCase("1"))
            // If the response to either question is yes then display positive as the measure value.
            if (primaryResult.getDwValue().equalsIgnoreCase("1")) {
                 primaryResult.setDwValue("POSITIVE");
            } else {
                 // If the response to both questions is no then display negative as the measure value.
                 if (correspondingResult != null) {
                     if (correspondingResult.getDwValue().equalsIgnoreCase("2")) {
                          primaryResult.setDwValue("NEGATIVE");
                     } else if (correspondingResult.getDwValue().equalsIgnoreCase("1")) {
                          // It must be yes - thus value is POSITIVE
                          primaryResult.setDwValue("POSITIVE");
                     } else {
                          badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                                  primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                                  "Issue with multiple PHQ results");
                          continue;
                     }
                 } else {
                     // No corresponding result - where is the 2nd result? -
                     badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                              primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                              "No corresponding value found for a 2 item screener with value of 'no'");
                     continue;

            }
        } else {
                 }
                                                                                                  if (primaryResult.getDwValue().equalsIgnoreCase("3") ||
            // If the response to either question is yes then display positive as the measure value.
            if (primaryResult.getDwValue().equalsIgnoreCase("3") ||
                              primaryResult.getDwValue().equalsIgnoreCase("4")) {
                 primaryResult.setDwValue("POSITIVE");
                                                                                                      primaryResult.getDwValue().equalsIgnoreCase("4"))
            } else {
                 // If the response to both questions is no then display negative as the measure value.
                 if (correspondingResult != null) {
                     if (primaryResult.getDwValue().equalsIgnoreCase("0") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("1") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("2")) {
                          primaryResult.setDwValue("NEGATIVE");
                     } else if (primaryResult.getDwValue().equalsIgnoreCase("3") ||
                                      primaryResult.getDwValue().equalsIgnoreCase("4")) {
                          // It must be yes - thus value is POSITIVE
                          primaryResult.setDwValue("POSITIVE");
                     } else {
                          badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                                  primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                                  "Issue with multiple PHQ results");
                          continue;
                     }
                 } else {
                     // No corresponding result - where is the 2nd result? -
                     badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER,
                              primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ",
                              "No corresponding value found for a 2 item screener with value of 'no'");
                     continue;
                 }
            }
        }

        Map<String, Object> transformedResult = resultTransformer.transformResult(sourcePatient, primaryResult);

        if (null != transformedResult) {
            retVal.add(new PatientDataUpdateCommand(CommandType.RESULT, sourcePatient, transformedResult));
        }
    }

    return retVal;
}
Compound Result Handler
    CompoundResultHandler                CompoundResultClassifier

                                        isNegative()
                                        isPositive()




                                     AbstractCompoundResultClassifier

                                     toNumber()




                  QueensCompoundResultClassifier            StandardCompoundResultClassifier

                 isNegative()                             isNegative()
                 isPositive()                             isPositive()
Compound Result Handler
      CompoundResultHandler                CompoundResultClassifier

                                          isNegative()
                                          isPositive()




                                       AbstractCompoundResultClassifier

                                       toNumber()




                    QueensCompoundResultClassifier            StandardCompoundResultClassifier

                   isNegative()                             isNegative()
                   isPositive()                             isPositive()




 Commonality                         Variability                               Resolution
                                                                              Inheritance
  Behaviour                       Implementation
                                                                           (Object-Oriented)
Compound Result Handler
       CompoundResultHandler                CompoundResultClassifier

                                           isNegative()
                                           isPositive()




                                        AbstractCompoundResultClassifier

                                        toNumber()




                     QueensCompoundResultClassifier            StandardCompoundResultClassifier

                    isNegative()                             isNegative()
                    isPositive()                             isPositive()




 Commonality                          Variability                               Resolution

Implementation                            None                                   Base Class
Commonality and Variability Analysis: Avoiding Duplicate Code
Code Visibility
Reading
Reading
Commonality and Variability Analysis: Avoiding Duplicate Code
Reading
The Pragmatic Programmer: From Journeyman to Master
Andrew Hunt and Dave Thomas

Extreme Programming Explained: Embrace Change
Kent Beck and Cynthia Andres

Test Driven Development: By Example
Kent Beck

Object-Oriented Software Construction
Bertrand Meyer
Reading
Clean Code: A Handbook of Agile Software
Craftsmanship Robert C. Martin

Design Patterns: Elements of Reusable Object-Oriented
Software Erich Gamma, Richard Helm, Ralph Johnson,
and John Vlissides

Multi-Paradigm Design for C++
James O. Coplien

Lean Architecture: for Agile Software Development
James O. Coplien and Gertrud Bjørnvig
Photo Credits
http://www.flickr.com/photos/27558040@N00/4151899795/



http://www.flickr.com/photos/popilop/331357312/



http://www.flickr.com/photos/arlette/3260468/



http://www.flickr.com/photos/36829973@N04/3546657245/

More Related Content

PDF
qooxdoo Form Management
PDF
Java 8 DOs and DON'Ts - javaBin Oslo May 2015
PPTX
Python 표준 라이브러리
PDF
Python 2.5 reference card (2009)
PDF
The Ring programming language version 1.3 book - Part 83 of 88
PDF
Software architecture2008 ejbql-quickref
PDF
Swift for TensorFlow - CoreML Personalization
PPT
Xm lparsers
qooxdoo Form Management
Java 8 DOs and DON'Ts - javaBin Oslo May 2015
Python 표준 라이브러리
Python 2.5 reference card (2009)
The Ring programming language version 1.3 book - Part 83 of 88
Software architecture2008 ejbql-quickref
Swift for TensorFlow - CoreML Personalization
Xm lparsers

What's hot (20)

PPTX
Ahda exploration
PPTX
11. session 11 functions and objects
PDF
The Ring programming language version 1.5.2 book - Part 33 of 181
PDF
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
PDF
The Ring programming language version 1.2 book - Part 22 of 84
ZIP
Elementary Sort
PDF
The Ring programming language version 1.5.3 book - Part 33 of 184
PPTX
Basic java, java collection Framework and Date Time API
PDF
The Ring programming language version 1.9 book - Part 41 of 210
PDF
The Ring programming language version 1.5.2 book - Part 32 of 181
PDF
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
PDF
The Ring programming language version 1.6 book - Part 35 of 189
PDF
Scala - en bedre og mere effektiv Java?
PDF
Scala DSLの作り方
PDF
1. python
PDF
.NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ...
PPTX
Scala best practices
PDF
Python's magic methods
PDF
The Ring programming language version 1.7 book - Part 41 of 196
PDF
Jquery.cheatsheet.1.4
Ahda exploration
11. session 11 functions and objects
The Ring programming language version 1.5.2 book - Part 33 of 181
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
The Ring programming language version 1.2 book - Part 22 of 84
Elementary Sort
The Ring programming language version 1.5.3 book - Part 33 of 184
Basic java, java collection Framework and Date Time API
The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.5.2 book - Part 32 of 181
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
The Ring programming language version 1.6 book - Part 35 of 189
Scala - en bedre og mere effektiv Java?
Scala DSLの作り方
1. python
.NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ...
Scala best practices
Python's magic methods
The Ring programming language version 1.7 book - Part 41 of 196
Jquery.cheatsheet.1.4
Ad

Similar to Commonality and Variability Analysis: Avoiding Duplicate Code (20)

PDF
An Introduction to RxJava
PDF
OrderTest.javapublic class OrderTest {       Get an arra.pdf
PPT
Oop lecture7
PDF
Module 4
PPT
Functional Programming
PDF
13 advanced-swing
PDF
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
PDF
Practical cats
PPT
Java Generics for Dummies
PDF
12advanced Swing
PDF
JUnit Kung Fu: Getting More Out of Your Unit Tests
PDF
Google Guava for cleaner code
PPTX
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
KEY
関数潮流(Function Tendency)
PPTX
Working With JQuery Part1
PPT
Tips and Tricks of Developing .NET Application
DOCX
Java programs
PPT
Lo Mejor Del Pdc2008 El Futrode C#
PPTX
Java 8 Examples
PDF
Create a menu-driven program that will accept a collection of non-ne.pdf
An Introduction to RxJava
OrderTest.javapublic class OrderTest {       Get an arra.pdf
Oop lecture7
Module 4
Functional Programming
13 advanced-swing
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
Practical cats
Java Generics for Dummies
12advanced Swing
JUnit Kung Fu: Getting More Out of Your Unit Tests
Google Guava for cleaner code
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
関数潮流(Function Tendency)
Working With JQuery Part1
Tips and Tricks of Developing .NET Application
Java programs
Lo Mejor Del Pdc2008 El Futrode C#
Java 8 Examples
Create a menu-driven program that will accept a collection of non-ne.pdf
Ad

More from Alistair McKinnell (14)

PDF
Succeeding with Specification by Example
PDF
Don't Settle for Poor Names (Or Poor Design)
PDF
Don't Settle for Poor Names
PDF
The Boy Scout Rule
PDF
Advanced Developer Testing
PDF
What Can Journalists Teach Developers About Writing Source Code?
PDF
Ubiquitous Testing
PDF
Simple Design
KEY
Agile Tour Shanghai December 2011
KEY
Pair Programming
KEY
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
PPT
The Story of a Story
PPT
The Testing Landscape
PPT
Struggling to Create Maintainable Unit Tests?
Succeeding with Specification by Example
Don't Settle for Poor Names (Or Poor Design)
Don't Settle for Poor Names
The Boy Scout Rule
Advanced Developer Testing
What Can Journalists Teach Developers About Writing Source Code?
Ubiquitous Testing
Simple Design
Agile Tour Shanghai December 2011
Pair Programming
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
The Story of a Story
The Testing Landscape
Struggling to Create Maintainable Unit Tests?

Recently uploaded (20)

PPTX
sap open course for s4hana steps from ECC to s4
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Machine learning based COVID-19 study performance prediction
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Empathic Computing: Creating Shared Understanding
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Encapsulation theory and applications.pdf
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPT
Teaching material agriculture food technology
PPTX
Big Data Technologies - Introduction.pptx
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
MYSQL Presentation for SQL database connectivity
sap open course for s4hana steps from ECC to s4
Encapsulation_ Review paper, used for researhc scholars
Machine learning based COVID-19 study performance prediction
Advanced methodologies resolving dimensionality complications for autism neur...
Assigned Numbers - 2025 - Bluetooth® Document
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
gpt5_lecture_notes_comprehensive_20250812015547.pdf
NewMind AI Weekly Chronicles - August'25-Week II
Empathic Computing: Creating Shared Understanding
20250228 LYD VKU AI Blended-Learning.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Building Integrated photovoltaic BIPV_UPV.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Encapsulation theory and applications.pdf
MIND Revenue Release Quarter 2 2025 Press Release
Teaching material agriculture food technology
Big Data Technologies - Introduction.pptx
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Agricultural_Statistics_at_a_Glance_2022_0.pdf
MYSQL Presentation for SQL database connectivity

Commonality and Variability Analysis: Avoiding Duplicate Code

  • 1. The First 100 Hours: Commonality and Variability Analysis Jason Cheong-Kee-You @jpcky www.mightyjupiter.com Alistair McKinnell @amckinnell www.valuablecode.com
  • 3. Commonality and Variability Analysis Avoiding Duplicate Code
  • 5. Exercise 1. Did you write any code last year? If so, how many lines of code? 2. How many lines of code in your code base? 3. Percentage of duplicate code?
  • 11. Avoiding Duplicate Code DRY: Don’t Repeat Yourself
  • 12. Avoiding Duplicate Code DRY: Don’t Repeat Yourself Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
  • 14. Avoiding Duplicate Code Once and Only Once
  • 15. Avoiding Duplicate Code Once and Only Once Data, structure, or logic should exist in only one place in the system.
  • 17. Avoiding Duplicate Code Test-Driven Development
  • 18. Avoiding Duplicate Code Test-Driven Development 1. Write new code only if an automated test has failed.
  • 19. Avoiding Duplicate Code Test-Driven Development 1. Write new code only if an automated test has failed. 2. Eliminate duplication.
  • 21. Avoiding Duplicate Code Single Choice Principle
  • 22. Avoiding Duplicate Code Single Choice Principle Whenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list.
  • 24. Avoiding Duplicate Code Duplication may be the root of all evil in software.
  • 27. Exercise What are the consequences of duplicate code?
  • 28. Exercise What are the consequences of duplicate code? Consider both good and evil.
  • 31. Exercise How does duplicate code come about?
  • 32. Exercise How does duplicate code come about? Make a Top 3 list.
  • 35. Alistair’s Contention Copy and Paste leads to the creation of duplicate code.
  • 36. Alistair’s Contention Copy and Paste leads to the creation of duplicate code. Developers lack the thinking tools and the development skills to avoid the duplication.
  • 38. Select Options public static List<SelectOption> createEndMonthList(Date expiryDate) { List<SelectOption> monthList = new ArrayList<SelectOption>(); int month = getDateMonth(expiryDate); for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(true); } else { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(false); } monthList.add(option); } return monthList; }
  • 39. Select Options public static List<SelectOption> createEndMonthList(Date expiryDate) { List<SelectOption> monthList = new ArrayList<SelectOption>(); int month = getDateMonth(expiryDate); for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(true); } else { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(false); } monthList.add(option); } return monthList; }
  • 40. Select Options public static List<SelectOption> createEndMonthList(Date expiryDate) { List<SelectOption> monthList = new ArrayList<SelectOption>(); int month = getDateMonth(expiryDate); for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(true); } else { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(false); } monthList.add(option); } return monthList; }
  • 41. Select Options public static List<SelectOption> createEndMonthList(Date expiryDate) { List<SelectOption> monthList = new ArrayList<SelectOption>(); int month = getDateMonth(expiryDate); for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(true); } else { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(false); } monthList.add(option); } return monthList; }
  • 42. Select Options public static List<SelectOption> createEndMonthList(Date expiryDate) { List<SelectOption> monthList = new ArrayList<SelectOption>(); int month = getDateMonth(expiryDate); for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(true); } else { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(false); } monthList.add(option); } return monthList; }
  • 43. Select Options public static List<SelectOption> createEndMonthList(Date expiryDate) { List<SelectOption> monthList = new ArrayList<SelectOption>(); int month = getDateMonth(expiryDate); for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(true); } else { option.setLabel(String.valueOf(intLooper)); option.setValue(String.valueOf(intLooper)); option.setSelected(false); } monthList.add(option); } return monthList; }
  • 44. Select Options SelectOptions SelectOptionsSource create() getFirst() getLast() isSelected() Commonality Variability Resolution Data Structure Value of State Simple Java Type
  • 45. Select Options SelectOptions SelectOptionsSource create() getFirst() getLast() isSelected() Parameter Object
  • 46. Select Options SelectOptions SelectOptionsSource create() getFirst() getLast() isSelected() Commonality Variability Resolution Encapsulate Behaviour Collaborator Collection
  • 47. Select Options SelectOptions SelectOptionsSource create() getFirst() getLast() isSelected() Encapsulate Collection
  • 49. Select Options Extra public static List<SelectOption> createProvinceList(String selectedProvince) { List<SelectOption> provinceList = new ArrayList<SelectOption>(); List<String> provinces = asList("AB", "BC", "MB", "NB", "NL", "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT"); for (int intLooper = 0; intLooper < provinces.size(); intLooper++) { SelectOption option = new SelectOption(); if (selectedProvince.equals(provinces.get(intLooper))) { option.setLabel(provinces.get(intLooper)); option.setValue(provinces.get(intLooper)); option.setSelected(true); } else { option.setLabel(provinces.get(intLooper)); option.setValue(provinces.get(intLooper)); option.setSelected(false); } provinceList.add(option); } return provinceList; }
  • 50. Select Options Extra public static List<SelectOption> createProvinceList(String selectedProvince) { List<SelectOption> provinceList = new ArrayList<SelectOption>(); List<String> provinces = asList("AB", "BC", "MB", "NB", "NL", "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT"); for (int intLooper = 0; intLooper < provinces.size(); intLooper++) { SelectOption option = new SelectOption(); if (selectedProvince.equals(provinces.get(intLooper))) { option.setLabel(provinces.get(intLooper)); option.setValue(provinces.get(intLooper)); option.setSelected(true); } else { option.setLabel(provinces.get(intLooper)); option.setValue(provinces.get(intLooper)); option.setSelected(false); } provinceList.add(option); } return provinceList; }
  • 51. Select Options Extra List<String> provinces = asList("AB", "BC", "MB", "NB", "NL", "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT");
  • 52. Select Options Extra List<String> provinces = asList("AB", "BC", "MB", "NB", "NL", "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT"); public enum Province { AB, BC, MB, NB, NL, NT, NS, NU, ON, PE, QC, SK, YT; } Commonality Variability Resolution A small set of Data Structure enum values
  • 53. Select Options Extra public enum Province { AB, BC, MB, NB, NL, NT, NS, NU, ON, PE, QC, SK, YT; } Single Choice Principle Whenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list.
  • 54. Select Options Extra public static List<SelectOption> createEndMonthList(Date expiryDate) { for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); } public static List<SelectOption> createProvinceList(String selectedProvince) { for (int intLooper = 0; intLooper < provinces.size(); intLooper++) { SelectOption option = new SelectOption(); if (selectedProvince.equals(provinces.get(intLooper))) { option.setLabel(provinces.get(intLooper)); }
  • 55. Select Options Extra public static List<SelectOption> createEndMonthList(Date expiryDate) { for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); } public static List<SelectOption> createProvinceList(String selectedProvince) { for (int intLooper = 0; intLooper < provinces.size(); intLooper++) { SelectOption option = new SelectOption(); if (selectedProvince.equals(provinces.get(intLooper))) { option.setLabel(provinces.get(intLooper)); }
  • 56. Select Options Extra public static List<SelectOption> createEndMonthList(Date expiryDate) { for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); } public static List<SelectOption> createProvinceList(String selectedProvince) { for (int intLooper = 0; intLooper < provinces.size(); intLooper++) { SelectOption option = new SelectOption(); if (selectedProvince.equals(provinces.get(intLooper))) { option.setLabel(provinces.get(intLooper)); }
  • 57. Select Options Extra public static List<SelectOption> createEndMonthList(Date expiryDate) { for (int intLooper = 1; intLooper <= 12; intLooper++) { SelectOption option = new SelectOption(); if (month == intLooper) { option.setLabel(String.valueOf(intLooper)); } public static List<SelectOption> createProvinceList(String selectedProvince) { for (int intLooper = 0; intLooper < provinces.size(); intLooper++) { SelectOption option = new SelectOption(); if (selectedProvince.equals(provinces.get(intLooper))) { option.setLabel(provinces.get(intLooper)); }
  • 58. Select Options Extra String Iterable iterator() SelectOptions SelectOptionsSource create() isSelected() IntegerRangeSource ProvinceSource iterator() iterator() isSelected() isSelected()
  • 59. Select Options Extra String Iterable iterator() SelectOptions SelectOptionsSource create() isSelected() IntegerRangeSource ProvinceSource iterator() iterator() isSelected() isSelected()
  • 60. Select Options Extra String Iterable iterator() SelectOptions SelectOptionsSource create() isSelected() IntegerRangeSource ProvinceSource iterator() iterator() isSelected() isSelected() Commonality Variability Resolution Collection Values Iterator
  • 61. Select Options Extra String Iterable iterator() SelectOptions SelectOptionsSource create() isSelected() IntegerRangeSource ProvinceSource iterator() iterator() isSelected() isSelected() Commonality Variability Resolution Collection Type Generics
  • 62. Select Options Extra String Iterable iterator() SelectOptions SelectOptionsSource create() isSelected() IntegerRangeSource ProvinceSource iterator() iterator() isSelected() isSelected() Commonality Variability Resolution Inheritance Behaviour Implementation (Object-Oriented)
  • 64. Compound Result Handler public Collection<IRegCommand> processCompondResults(Patient sourcePatient, Collection<Result> results) { Collection<IRegCommand> retVal = new ArrayList<IRegCommand>(); Set<Result> resultsMarkedForRemoval = new HashSet<Result>(); Set<Result> resultsProcessed = new HashSet<Result>(); for (Result primaryResult : results) { if (isResultProcessed(resultsProcessed, primaryResult)) { continue; } resultsProcessed.add(primaryResult); Result correspondingResult = getCorrespondingResult(primaryResult, results); if (correspondingResult != null) { resultsProcessed.add(correspondingResult); resultsMarkedForRemoval.add(correspondingResult); } if (!sourcePatient.getDataWarehouse().equals(DataWarehouseTag.QHN)) { // If the response to either question is yes then display positive as the measure value. if (primaryResult.getDwValue().equalsIgnoreCase("1")) { primaryResult.setDwValue("POSITIVE"); } else { // If the response to both questions is no then display negative as the measure value. if (correspondingResult != null) { if (correspondingResult.getDwValue().equalsIgnoreCase("2")) { primaryResult.setDwValue("NEGATIVE"); } else if (correspondingResult.getDwValue().equalsIgnoreCase("1")) { // It must be yes - thus value is POSITIVE primaryResult.setDwValue("POSITIVE"); } else { badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "Issue with multiple PHQ results"); continue; } } else { // No corresponding result - where is the 2nd result? - badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "No corresponding value found for a 2 item screener with value of 'no'"); continue; } } } else { // If the response to either question is yes then display positive as the measure value. if (primaryResult.getDwValue().equalsIgnoreCase("3") || primaryResult.getDwValue().equalsIgnoreCase("4")) { primaryResult.setDwValue("POSITIVE"); } else { // If the response to both questions is no then display negative as the measure value. if (correspondingResult != null) { if (primaryResult.getDwValue().equalsIgnoreCase("0") || primaryResult.getDwValue().equalsIgnoreCase("1") || primaryResult.getDwValue().equalsIgnoreCase("2")) { primaryResult.setDwValue("NEGATIVE"); } else if (primaryResult.getDwValue().equalsIgnoreCase("3") || primaryResult.getDwValue().equalsIgnoreCase("4")) { // It must be yes - thus value is POSITIVE primaryResult.setDwValue("POSITIVE"); } else { badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "Issue with multiple PHQ results"); continue; } } else { // No corresponding result - where is the 2nd result? - badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "No corresponding value found for a 2 item screener with value of 'no'"); continue; } } } Map<String, Object> transformedResult = resultTransformer.transformResult(sourcePatient, primaryResult); if (null != transformedResult) { retVal.add(new PatientDataUpdateCommand(CommandType.RESULT, sourcePatient, transformedResult)); } } return retVal; }
  • 65. Compound Result Handler public Collection<IRegCommand> processCompondResults(Patient sourcePatient, Collection<Result> results) { Collection<IRegCommand> retVal = new ArrayList<IRegCommand>(); Set<Result> resultsMarkedForRemoval = new HashSet<Result>(); Set<Result> resultsProcessed = new HashSet<Result>(); for (Result primaryResult : results) { if (isResultProcessed(resultsProcessed, primaryResult)) { continue; } resultsProcessed.add(primaryResult); Result correspondingResult = getCorrespondingResult(primaryResult, results); if (correspondingResult != null) { resultsProcessed.add(correspondingResult); } resultsMarkedForRemoval.add(correspondingResult); if (!sourcePatient.getDataWarehouse() if (!sourcePatient.getDataWarehouse().equals(DataWarehouseTag.QHN)) { // If the response to either question is yes then display positive as the measure value. if (primaryResult.getDwValue().equalsIgnoreCase("1")) { primaryResult.setDwValue("POSITIVE"); .equals(DataWarehouseTag.QHN)) { } else { // If the response to both questions is no then display negative as the measure value. if (correspondingResult != null) { if (correspondingResult.getDwValue().equalsIgnoreCase("2")) { primaryResult.setDwValue("NEGATIVE"); } else if (correspondingResult.getDwValue().equalsIgnoreCase("1")) { // It must be yes - thus value is POSITIVE primaryResult.setDwValue("POSITIVE"); } else { badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "Issue with multiple PHQ results"); continue; } } else { // No corresponding result - where is the 2nd result? - badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "No corresponding value found for a 2 item screener with value of 'no'"); continue; } } } else { // If the response to either question is yes then display positive as the measure value. if (primaryResult.getDwValue().equalsIgnoreCase("3") || primaryResult.getDwValue().equalsIgnoreCase("4")) { primaryResult.setDwValue("POSITIVE"); } else { // If the response to both questions is no then display negative as the measure value. if (correspondingResult != null) { if (primaryResult.getDwValue().equalsIgnoreCase("0") || primaryResult.getDwValue().equalsIgnoreCase("1") || primaryResult.getDwValue().equalsIgnoreCase("2")) { primaryResult.setDwValue("NEGATIVE"); } else if (primaryResult.getDwValue().equalsIgnoreCase("3") || primaryResult.getDwValue().equalsIgnoreCase("4")) { // It must be yes - thus value is POSITIVE primaryResult.setDwValue("POSITIVE"); } else { badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "Issue with multiple PHQ results"); continue; } } else { // No corresponding result - where is the 2nd result? - badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "No corresponding value found for a 2 item screener with value of 'no'"); continue; } } } Map<String, Object> transformedResult = resultTransformer.transformResult(sourcePatient, primaryResult); if (null != transformedResult) { retVal.add(new PatientDataUpdateCommand(CommandType.RESULT, sourcePatient, transformedResult)); } } return retVal; }
  • 66. Compound Result Handler public Collection<IRegCommand> processCompondResults(Patient sourcePatient, Collection<Result> results) { Collection<IRegCommand> retVal = new ArrayList<IRegCommand>(); Set<Result> resultsMarkedForRemoval = new HashSet<Result>(); Set<Result> resultsProcessed = new HashSet<Result>(); for (Result primaryResult : results) { if (isResultProcessed(resultsProcessed, primaryResult)) { continue; } resultsProcessed.add(primaryResult); Result correspondingResult = getCorrespondingResult(primaryResult, results); if (correspondingResult != null) { resultsProcessed.add(correspondingResult); } resultsMarkedForRemoval.add(correspondingResult); if (!sourcePatient.getDataWarehouse().equals(DataWarehouseTag.QHN)) { if (primaryResult.getDwValue().equalsIgnoreCase("1")) // If the response to either question is yes then display positive as the measure value. if (primaryResult.getDwValue().equalsIgnoreCase("1")) { primaryResult.setDwValue("POSITIVE"); } else { // If the response to both questions is no then display negative as the measure value. if (correspondingResult != null) { if (correspondingResult.getDwValue().equalsIgnoreCase("2")) { primaryResult.setDwValue("NEGATIVE"); } else if (correspondingResult.getDwValue().equalsIgnoreCase("1")) { // It must be yes - thus value is POSITIVE primaryResult.setDwValue("POSITIVE"); } else { badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "Issue with multiple PHQ results"); continue; } } else { // No corresponding result - where is the 2nd result? - badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "No corresponding value found for a 2 item screener with value of 'no'"); continue; } } else { } if (primaryResult.getDwValue().equalsIgnoreCase("3") || // If the response to either question is yes then display positive as the measure value. if (primaryResult.getDwValue().equalsIgnoreCase("3") || primaryResult.getDwValue().equalsIgnoreCase("4")) { primaryResult.setDwValue("POSITIVE"); primaryResult.getDwValue().equalsIgnoreCase("4")) } else { // If the response to both questions is no then display negative as the measure value. if (correspondingResult != null) { if (primaryResult.getDwValue().equalsIgnoreCase("0") || primaryResult.getDwValue().equalsIgnoreCase("1") || primaryResult.getDwValue().equalsIgnoreCase("2")) { primaryResult.setDwValue("NEGATIVE"); } else if (primaryResult.getDwValue().equalsIgnoreCase("3") || primaryResult.getDwValue().equalsIgnoreCase("4")) { // It must be yes - thus value is POSITIVE primaryResult.setDwValue("POSITIVE"); } else { badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "Issue with multiple PHQ results"); continue; } } else { // No corresponding result - where is the 2nd result? - badDataLogger.logBadData(sourcePatient.getExternalId(), Measure.NAME_2ITEMSCREENER, primaryResult.getDwValue() + " (" + primaryResult.getEventDateTime() + ") ", "No corresponding value found for a 2 item screener with value of 'no'"); continue; } } } Map<String, Object> transformedResult = resultTransformer.transformResult(sourcePatient, primaryResult); if (null != transformedResult) { retVal.add(new PatientDataUpdateCommand(CommandType.RESULT, sourcePatient, transformedResult)); } } return retVal; }
  • 67. Compound Result Handler CompoundResultHandler CompoundResultClassifier isNegative() isPositive() AbstractCompoundResultClassifier toNumber() QueensCompoundResultClassifier StandardCompoundResultClassifier isNegative() isNegative() isPositive() isPositive()
  • 68. Compound Result Handler CompoundResultHandler CompoundResultClassifier isNegative() isPositive() AbstractCompoundResultClassifier toNumber() QueensCompoundResultClassifier StandardCompoundResultClassifier isNegative() isNegative() isPositive() isPositive() Commonality Variability Resolution Inheritance Behaviour Implementation (Object-Oriented)
  • 69. Compound Result Handler CompoundResultHandler CompoundResultClassifier isNegative() isPositive() AbstractCompoundResultClassifier toNumber() QueensCompoundResultClassifier StandardCompoundResultClassifier isNegative() isNegative() isPositive() isPositive() Commonality Variability Resolution Implementation None Base Class
  • 75. Reading The Pragmatic Programmer: From Journeyman to Master Andrew Hunt and Dave Thomas Extreme Programming Explained: Embrace Change Kent Beck and Cynthia Andres Test Driven Development: By Example Kent Beck Object-Oriented Software Construction Bertrand Meyer
  • 76. Reading Clean Code: A Handbook of Agile Software Craftsmanship Robert C. Martin Design Patterns: Elements of Reusable Object-Oriented Software Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides Multi-Paradigm Design for C++ James O. Coplien Lean Architecture: for Agile Software Development James O. Coplien and Gertrud Bjørnvig

Editor's Notes