Redundancy vs. dependencies: which is worse? (2008)
Conspicuously absent from this entire article is the word &quot;abstraction&quot;.<p>Oh, sorry, I just said a bad word, didn&#x27;t I? We&#x27;re not allowed to use the <i>a</i>-word around these parts, or people will think we&#x27;re being <i>enterprisey</i> and chase use away with pitchforks. What am I, some kinda <i>enterprise</i> programmer?<p>I can see why doing an &quot;extract to interface&quot; IDE command in the messy situation TFA describes would (rightly!) get this reaction. Of course that&#x27;s just adding more needless complexity to an already needlessly complex situation. But that&#x27;s not what good abstraction looks like. For some reason, everyone seems to get it in their head that abstraction is supposed to be some sort of list of features you support. So you take each public class Foo and extract them to an interface IFoo and you have your list of features. Abstraction!<p>No. Good abstraction describes your <i>needs</i>. That&#x27;s it! If your module needs to do something, but doesn&#x27;t want to be responsible for the exact implementation of that thing, then you define an abstraction which describes that need. It will be implemented by whoever needs your module.<p>&gt; You can choose between having modules A and B using a module C doing something, or have them do it themselves. What&#x27;s your call?<p>A defines abstractions describing what it needs to do its job, and so does B. Since A and B have different responsibilities, these are two separate pieces of code, even if they look basically the same right now.<p>Now you have lots of options, and you can vary between them easily depending on what makes sense:<p>- A and B can implement the abstractions C needs, and then use C. So A -&gt; C and B -&gt; C. (&quot;-&gt;&quot; meaning &quot;depends on&quot;). The code exists in isolated corners of A and B so it can be moved easily later.<p>- C can implement A&#x27;s and B&#x27;s abstractions, so C -&gt; A and C -&gt; B. The code exists in isolated corners of C, so it can be moved easily later.<p>- Leave A, B, and C <i>completely independent</i> of one another. Write a small module <i>ac</i>, which provides implementations for A in terms of C, and a small module <i>ad</i>, which provides implementations for B in terms of C. Now you have <i>no dependencies whatsoever</i> between your major modules, and you&#x27;ve introduced small adapter modules that you can throw away later.<p>- Leave A, B, and C <i>completely independent</i> of one another. Your end application handles stitching them together (like above, but <i>ab</i> and <i>ac</i> are just sitting inside your end application).<p>&gt; Rumors tell that [XParam&#x27;s] original host project uses &lt;5% of its features.<p>Let the marketing people think in terms of &quot;features&quot;. You should be thinking in terms of <i>needs</i>. You can spend months implementing features that you don&#x27;t need. It&#x27;s much harder to implement a need you don&#x27;t need. An that&#x27;s what abstractions are: a description of what you need to do your job.