Well, that’s programming: it’s not about proving one point. It’s about proving every possible point. The level of ability to abstract should be much higher than the ability to add an extra recipe.
This! I know that it's often tempting to demonstrate your abilities in the software you create. But introducing abstractions and DRY code is only necessary, when you have a complex problem with nany repeating parts that would become unmaintainable otherwise. If that is not the case, keep it simple. This is similar to premature optimization.
That's exactly the point I want to bring across. As simple as possible, but not simpler. However, solving one problem, but causing dozens down the line is not engineering, even though your problem is 'the simplest'.
You see, in the 'problem solution lattice' there are multiple bottoms [1] (most simple solution). Knowing which 'simplest solution' is the best, depends on your knowledge of the problem, your anticipation on how the problem might be extended in the future, your array of possible solutions, etc. etc.
For example, the original solution to the recipe problem in OP uses a very sequential and object oriented approach. That solution is one of the infinite number of solutions that fixes the problem. The extension of the problem (an extra recipe) plots a graph upwards through the latice towards another solution that fixes both the original problem, as well as the new problem. The number of steps required (the distance) is dependent on choice of the original solution. And since there are multiple bottoms, we could have a solution that is not able to be further simplified, even though there is a parallel bottom, that has a much shorter distance to the second solution.
Writing maintainable software is about solving the problem you actually have as simply as possible. Introduce abstractions only when you need to.