• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Commonality and Variability Analysis: Avoiding Duplicate Code
 

Commonality and Variability Analysis: Avoiding Duplicate Code

on

  • 2,297 views

Duplicate code is something to be avoided. And yet, everyday developers make copies of working code, make edits to the copy, and create duplicate code. ...

Duplicate code is something to be avoided. And yet, everyday developers make copies of working code, make edits to the copy, and create duplicate code.

Some developers have the discipline and the skill to refactor to eliminate this duplicate code. Many do not.

Statistics

Views

Total Views
2,297
Views on SlideShare
2,037
Embed Views
260

Actions

Likes
1
Downloads
13
Comments
0

3 Embeds 260

http://recoverlee.com 254
http://jhlee8379.cafe24.com 5
http://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

CC Attribution License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Commonality and Variability Analysis: Avoiding Duplicate Code Commonality and Variability Analysis: Avoiding Duplicate Code Presentation Transcript

  • The First 100 Hours: Commonality and Variability AnalysisJason Cheong-Kee-You @jpcky www.mightyjupiter.com Alistair McKinnell@amckinnell www.valuablecode.com
  • Commonality andVariability Analysis
  • Commonality and Variability AnalysisAvoiding Duplicate Code
  • Exercise
  • Exercise1. 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
  • ExerciseWhat are the consequences ofduplicate code?
  • ExerciseWhat are the consequences ofduplicate code?Consider both good and evil.
  • Exercise
  • Exercise
  • ExerciseHow does duplicate codecome about?
  • ExerciseHow does duplicate codecome about?Make a Top 3 list.
  • Alistair’s Contention
  • Alistair’s ContentionCopy and Paste leads to thecreation of duplicate code.
  • Alistair’s ContentionCopy and Paste leads to thecreation of duplicate code.Developers lack the thinking toolsand the development skills to avoidthe duplication.
  • Duplicate Code:Select Options
  • Select Optionspublic 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 Optionspublic 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 Optionspublic 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 Optionspublic 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 Optionspublic 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 Optionspublic 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 SelectOptionsSourcecreate() getFirst() getLast() isSelected() Commonality Variability Resolution Data Structure Value of State Simple Java Type
  • Select Options SelectOptions SelectOptionsSourcecreate() getFirst() getLast() isSelected() Parameter Object
  • Select Options SelectOptions SelectOptionsSourcecreate() getFirst() getLast() isSelected() Commonality Variability Resolution Encapsulate Behaviour Collaborator Collection
  • Select Options SelectOptions SelectOptionsSourcecreate() getFirst() getLast() isSelected() Encapsulate Collection
  • Duplicate Code:Select Options Extra
  • Select Options Extrapublic 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 Extrapublic 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 ExtraList<String> provinces = asList("AB", "BC", "MB", "NB", "NL", "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT");
  • Select Options ExtraList<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 Extrapublic 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 Extrapublic 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 Extrapublic 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 Extrapublic 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 Extrapublic 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 Handlerpublic 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 Handlerpublic 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 Handlerpublic 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 ResolutionImplementation None Base Class
  • Code Visibility
  • Reading
  • Reading
  • ReadingThe Pragmatic Programmer: From Journeyman to MasterAndrew Hunt and Dave ThomasExtreme Programming Explained: Embrace ChangeKent Beck and Cynthia AndresTest Driven Development: By ExampleKent BeckObject-Oriented Software ConstructionBertrand Meyer
  • ReadingClean Code: A Handbook of Agile SoftwareCraftsmanship Robert C. MartinDesign Patterns: Elements of Reusable Object-OrientedSoftware Erich Gamma, Richard Helm, Ralph Johnson,and John VlissidesMulti-Paradigm Design for C++James O. CoplienLean Architecture: for Agile Software DevelopmentJames O. Coplien and Gertrud Bjørnvig
  • Photo Creditshttp://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/