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

Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfSeasiaInfotech2
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 

Recently uploaded (20)

Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdf
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 

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