// It suggests that it is a branching, but it is only a duplicate// It differs only in the input value, which is implemented inlinepublicbooleanisMultipleOriginAllowedForCountry(SearchFlightsForm form) {if (GstUserType.INTERNAL==userHelper.getCurrentUserUserType()) {returnisCountryInTheListOfAllowedMultipleOrigins(form.getPos().getCode()); } else {returnisCountryInTheListOfAllowedMultipleOrigins(userHelper.getCurrentUserPos()); }}
Example: Good: No duplicates, correct intention
publicbooleanisMultipleOriginAllowedForCountry(SearchFlightsForm form) {returnisCountryInTheListOfAllowedMultipleOrigins(getPosOfUser(form));}// Extracted funtionality can be tested tooprivateStringgetPosOfUser(SearchFlightsForm form) {returnGstUserType.INTERNAL==userHelper.getCurrentUserUserType() ?form.getPos().getCode() :userHelper.getCurrentUserPos();}
Example: Bad: Duplicated implementation with differences
// Cause: laziness of the developer// Cannot be found by a code checker// Blocks the development and the refactoring toopublicfinalvoidparse(finalString[] configs,finalString configPath,finalboolean flushAfterParse) {finalFileLocator locator =newFileLocator();try {if (getInputSource()!=null) {finalEdifactParser parser =newEdifactParser(getInputSource(), getHandler()); final String extendedConfigPath = StringUtils.isEmpty(configPath) ? "" : configPath + CharacterConstant.SLASH;
for (finalString config : configs) {finalFile grammarFile =locator.locate(extendedConfigPath + config +".xml");parser.addConfig(newConfig(config, grammarFile)); }parser.convert();if (flushAfterParse) {getHandler().flush(true); } } } catch (finalIOException e) {thrownewExtendedRuntimeException(e); } catch (finalExtendedException e) {thrownewExtendedRuntimeException(e); } finally {locator.releaseAll(); }}publicfinalvoidparse(finalConfig[] configs,finalboolean flushAfterParse) {finalFileLocator locator =newFileLocator();try {if (getInputSource()!=null) {finalEdifactParser parser =newEdifactParser(getInputSource(), getHandler());for (finalConfig config : configs) {parser.addConfig(config); }parser.convert();if (flushAfterParse) {getHandler().flush(true); } } } catch (finalIOException e) {thrownewExtendedRuntimeException(e); } catch (finalExtendedException e) {thrownewExtendedRuntimeException(e); } finally {locator.releaseAll(); }}// Other clean code issues in this example:// - Methods are doing more than one thing// - Inner dependency// - Not expressive validity check
Example: Bad: Duplicates differ only in values
// Bad intention: similar methods with very different names - how can be that?// Methods do what they tell but you CANNOT SEE it// It contains another duplication which can be expensive (e.g. database access)privatevoidfillOutCountriesForMultipleOrigin() {getSegments().get(0).setOrigin(countryAutoCompleteHelper.getCountryItemForAiportCode(getPosForMultipleOrigin()));if (JourneyType.OPEN_JAW.equals(getJourneyType())) { getSegments().get(1).setDestination(countryAutoCompleteHelper.getCountryItemForAiportCode(getPosForMultipleOrigin()));
}}privatevoidremoveCountriesForNormalFlights() {getSegments().get(0).setOrigin(null);if (JourneyType.OPEN_JAW.equals(getJourneyType())) {getSegments().get(1).setDestination(null); }}
Example: Good: Refactor value differences to input parameters
// Methods do what they tell and you CAN SEE itprivatevoidfillOutCountriesForMultipleOrigin() {setCountryForSegments(countryAutoCompleteHelper.getCountryItemForAiportCode(getPosForMultipleOrigin()));}privatevoidremoveCountriesForNormalFlights() {setCountryForSegments(null);}privatevoidsetCountryForSegments(AirportCityCodeItem country) {getSegments().get(0).setOrigin(country);if (JourneyType.OPEN_JAW.equals(getJourneyType())) {getSegments().get(1).setDestination(country); }}// It is not yet clean: magic numbers// It is not yet clean: why only two segments?