SlideShare a Scribd company logo
1 of 77
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.
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
Code Visibility
Reading
Reading
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

What's hot

11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objectsPhúc Đỗ
 
The Ring programming language version 1.5.2 book - Part 33 of 181
The Ring programming language version 1.5.2 book - Part 33 of 181The Ring programming language version 1.5.2 book - Part 33 of 181
The Ring programming language version 1.5.2 book - Part 33 of 181Mahmoud Samir Fayed
 
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲Mohammad Reza Kamalifard
 
The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 33 of 184
The Ring programming language version 1.5.3 book - Part 33 of 184The Ring programming language version 1.5.3 book - Part 33 of 184
The Ring programming language version 1.5.3 book - Part 33 of 184Mahmoud Samir Fayed
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIjagriti srivastava
 
The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.9 book - Part 41 of 210The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.9 book - Part 41 of 210Mahmoud Samir Fayed
 
The Ring programming language version 1.5.2 book - Part 32 of 181
The Ring programming language version 1.5.2 book - Part 32 of 181The Ring programming language version 1.5.2 book - Part 32 of 181
The Ring programming language version 1.5.2 book - Part 32 of 181Mahmoud Samir Fayed
 
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونیاسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونیMohammad Reza Kamalifard
 
The Ring programming language version 1.6 book - Part 35 of 189
The Ring programming language version 1.6 book - Part 35 of 189The Ring programming language version 1.6 book - Part 35 of 189
The Ring programming language version 1.6 book - Part 35 of 189Mahmoud Samir Fayed
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Jesper Kamstrup Linnet
 
.NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ...
.NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ....NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ...
.NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ...NETFest
 
Python's magic methods
Python's magic methodsPython's magic methods
Python's magic methodsReuven Lerner
 
The Ring programming language version 1.7 book - Part 41 of 196
The Ring programming language version 1.7 book - Part 41 of 196The Ring programming language version 1.7 book - Part 41 of 196
The Ring programming language version 1.7 book - Part 41 of 196Mahmoud Samir Fayed
 

What's hot (20)

Ahda exploration
Ahda explorationAhda exploration
Ahda exploration
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
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.5.2 book - Part 33 of 181The Ring programming language version 1.5.2 book - Part 33 of 181
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
The Ring programming language version 1.2 book - Part 22 of 84The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84
 
Elementary Sort
Elementary SortElementary Sort
Elementary Sort
 
The Ring programming language version 1.5.3 book - Part 33 of 184
The Ring programming language version 1.5.3 book - Part 33 of 184The Ring programming language version 1.5.3 book - Part 33 of 184
The Ring programming language version 1.5.3 book - Part 33 of 184
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
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.9 book - Part 41 of 210The Ring programming language version 1.9 book - Part 41 of 210
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.5.2 book - Part 32 of 181The Ring programming language version 1.5.2 book - Part 32 of 181
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
The Ring programming language version 1.6 book - Part 35 of 189The Ring programming language version 1.6 book - Part 35 of 189
The Ring programming language version 1.6 book - Part 35 of 189
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
Scala DSLの作り方
Scala DSLの作り方Scala DSLの作り方
Scala DSLの作り方
 
1. python
1. python1. python
1. python
 
.NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ...
.NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ....NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ...
.NET Fest 2018. Дмитрий Иванов. Иммутабельные структуры данных в .NET: зачем ...
 
Scala best practices
Scala best practicesScala best practices
Scala best practices
 
Python's magic methods
Python's magic methodsPython's magic methods
Python's magic methods
 
The Ring programming language version 1.7 book - Part 41 of 196
The Ring programming language version 1.7 book - Part 41 of 196The Ring programming language version 1.7 book - Part 41 of 196
The Ring programming language version 1.7 book - Part 41 of 196
 
Jquery.cheatsheet.1.4
Jquery.cheatsheet.1.4Jquery.cheatsheet.1.4
Jquery.cheatsheet.1.4
 

Similar to Commonality and Variability Analysis: Avoiding Duplicate Code

OrderTest.javapublic class OrderTest {       Get an arra.pdf
OrderTest.javapublic class OrderTest {         Get an arra.pdfOrderTest.javapublic class OrderTest {         Get an arra.pdf
OrderTest.javapublic class OrderTest {       Get an arra.pdfakkhan101
 
13 advanced-swing
13 advanced-swing13 advanced-swing
13 advanced-swingNataraj Dg
 
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfLECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfShashikantSathe3
 
Java Generics for Dummies
Java Generics for DummiesJava Generics for Dummies
Java Generics for Dummiesknutmork
 
12advanced Swing
12advanced Swing12advanced Swing
12advanced SwingAdil Jafri
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJohn Ferguson Smart Limited
 
Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner codeMite Mitreski
 
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum Ukraine
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)riue
 
Working With JQuery Part1
Working With JQuery Part1Working With JQuery Part1
Working With JQuery Part1saydin_soft
 
Tips and Tricks of Developing .NET Application
Tips and Tricks of Developing .NET ApplicationTips and Tricks of Developing .NET Application
Tips and Tricks of Developing .NET ApplicationJoni
 
Java programs
Java programsJava programs
Java programsjojeph
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Juan Pablo
 
Create a menu-driven program that will accept a collection of non-ne.pdf
Create a menu-driven program that will accept a collection of non-ne.pdfCreate a menu-driven program that will accept a collection of non-ne.pdf
Create a menu-driven program that will accept a collection of non-ne.pdfrajeshjangid1865
 

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

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

More from Alistair McKinnell

Succeeding with Specification by Example
Succeeding with Specification by ExampleSucceeding with Specification by Example
Succeeding with Specification by ExampleAlistair McKinnell
 
Don't Settle for Poor Names (Or Poor Design)
Don't Settle for Poor Names (Or Poor Design)Don't Settle for Poor Names (Or Poor Design)
Don't Settle for Poor Names (Or Poor Design)Alistair McKinnell
 
What Can Journalists Teach Developers About Writing Source Code?
What Can Journalists Teach Developers About Writing Source Code?What Can Journalists Teach Developers About Writing Source Code?
What Can Journalists Teach Developers About Writing Source Code?Alistair McKinnell
 
Agile Tour Shanghai December 2011
Agile Tour Shanghai December 2011Agile Tour Shanghai December 2011
Agile Tour Shanghai December 2011Alistair McKinnell
 
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic ToolAgile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic ToolAlistair McKinnell
 
Struggling to Create Maintainable Unit Tests?
Struggling to Create Maintainable Unit Tests?Struggling to Create Maintainable Unit Tests?
Struggling to Create Maintainable Unit Tests?Alistair McKinnell
 

More from Alistair McKinnell (14)

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

Recently uploaded

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 

Recently uploaded (20)

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 

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.
  • 33.
  • 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
  • 70.
  • 74.
  • 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

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n