You are right that changing essentially identical code is a code smell.
The question is why does it smell?
The answer is rarely because someone copied and pasted code (although you should definitely consider it in the presence of novice developers, or code generators). It is usually a symptom of a larger architectural decision. Whether that decision needs revision is contextual.
So we need an example to go into some detail here:
Assume the business handles Students and Teachers with two endpoints in the API (
/student). Lets also assume the database has a single
person table in the data base.
You can approach this by having a query that takes an argument and looks up people. Something like
exec people_in_role @role='teacher'.
Or you can take the approach of two separate queries.
exec students and
In the first approach you have applied the DRY principle and removed the duplication in the query. But you have also introduced the idea of a
Person into the business logic as the base type of both
In the second approach you have minimised the coupling between the domain concepts
Student keeping them independent and clean. On the other hand this has forced the database to expose two concepts as two stored procs, and duplicate what is essentially the same code.
Neither approach is strictly superior.
- Are you going to split the
People table apart? Option 2 fits this situation better, as it doesn't impose any higher level coupling in the domain logic. Thus allowing the table to be split and change independently. But you will pay the price for maintaining near identical code.
- Do you already have a
Person base class in the domain logic? Option 1 reduces code duplication. And aligns the Database with the domain logic for easier reasoning. But you will pay the price of having highly coupled domain logic.
In both cases what you are looking for is that sweet spot where the coupling isn't fighting how the system is being used, or being grown, but instead assists.