Right. There are two kinds of such refactoring / DRY-ing up the code:
1) Specialized helper sub-functions/classes to make the codeblocks DRY.
2) Functions/classes to make separate features DRY.
Problem arises when the design or understanding of the code doesn't reflect the realities of changes over time, forcing you to restart/revert, or making spaghetti code with optionals and whatnot to accomodate the rising complexity.
The agile approach would be to make the code that is easiest to change either way, and prevent being locked in to only one approach.
1) Specialized helper sub-functions/classes to make the codeblocks DRY.
2) Functions/classes to make separate features DRY.
Problem arises when the design or understanding of the code doesn't reflect the realities of changes over time, forcing you to restart/revert, or making spaghetti code with optionals and whatnot to accomodate the rising complexity.
The agile approach would be to make the code that is easiest to change either way, and prevent being locked in to only one approach.