Course progress0%
Course content

Module 1

Module 2

Module 3

Module 4

Module 5

Module 6

Module 7

Module 8

Module 9

Module 10

Module 11

Module 12

Module 13

Module 14

Module 15

Module 16

Module 17

Module 18

30 min

Avoid Duplication without Overengineering

Share one business rule where it has one meaning

By the end of this lesson

  • Share one business rule where it has one meaning
  • Recognize when similar code should remain separate

Similar text is not always the same rule

Two places calculate an order subtotal. They should agree. A separate operation calculates employee commission using similar multiplication. Should all three become one generic business function?

The DRY principle encourages keeping a piece of knowledge in one authoritative place. It does not require every similar expression to share an abstraction.

function calculateSubtotal(priceCents, quantity) {
  return priceCents * quantity;
}
function preparePreview(priceCents, quantity) {
  return calculateSubtotal(priceCents, quantity);
}
function prepareReceiptSubtotal(priceCents, quantity) {
  return calculateSubtotal(priceCents, quantity);
}
console.assert(preparePreview(500, 2) === prepareReceiptSubtotal(500, 2));

The wrapper functions illustrate two callers. In a real small program, call the shared function directly unless the wrappers represent additional meaningful workflow.

Guided tradeoff

A generic calculate(mode, value1, value2, flag) can remove duplicated lines while making callers harder to understand. Flags may reveal unrelated responsibilities forced into one function. Prefer a clear subtotal operation and a separate commission operation when their policies change independently.

Independent exercise

Two functions independently decide whether an order qualifies for a loyalty discount. One uses > 100, the other >= 100. Describe the investigation and refactor. Should you simply choose whichever version is shorter?

Correction

Confirm the actual threshold policy, write boundary tests, then extract one eligibility function used by both callers. The refactor should preserve the confirmed behavior, not randomly select one implementation. Keep the failing boundary case as a regression test.

Review

Refactoring changes structure while preserving intended behavior. First establish that behavior with examples; then remove duplicated knowledge. Abstractions should reduce the number of decisions a reader must understand, not add a configurable mini-language.

Lesson complete?

Your progress is saved on this device.