1. 10
  1.  

  2. 6

    Extensibility and re-usability are potential goals for system boundaries only. ..creating something that’s re-usable is pretty inherently about creating something that’s a system boundary, to some degree or another. And if you’re knowingly working on a system boundary… you’re knowingly working on something that supposed to be re-usable already. It’s pretty redundant to hail it as a design goal.

    This is great. I’ve been collecting anti-reuse, anti-abstraction links. Everytime I add one to my collection I’m going to share the whole thing.

    1. 4

      The part you quoted is also followed by:

      System boundaries are the danger zones of design. To whatever extent possible, we don’t want to create them unnecessarily. Any mistakes we make there are frozen, under threat of expensive breaking changes to fix.

      This is a nice counter to the approach of “all classes should be isolated”, “inject everything”, “never use ‘new’”, “mock everything”, etc. that I’ve encoutered in old jobs. It turns the implementation detail of internal code organisation boundaries (i.e. classes) into faux system boundaries, which makes them much more rigid and burdensome to change, slowing us down and discouraging refactoring.

    2. 1

      I think there are actually two distinct forms of “reusability” in the wild, which I like to distinguish between.

      Some things are reusable because they’re so small and simple that they can slot into solutions for all sorts of problems. Examples include unix utilities, JSON/protobuf/etc., arrays, linked lists, filesystems, SQlite (RDBMS servers like Postgres are debatable, I personally wouldn’t call them “simple”), key/value stores, etc.

      This is a good form of reusability, since this sort of code tends to be solving a well-specified (although abstract) problem, and can often be considered “finished”. Pulling out such functionality from a larger program hence reduces the amount of stuff we need to care about.

      Other things are reusable because they have so many hooks/options that we can configure them to plug into all sorts of solutions. Examples include stereotypical “enterprise ready” software, towering monoliths of code like GCC and GHC, “frameworks” and “ecosystems” like Symfony, Drupal, Wordpress, etc.

      This second form of “reusability” is often underisable. We need to go out of our way to support other use-cases, which may not even exist. This sort of software is often modelling some concrete, domain-specific concern like “users” or “reports”, which are informal enough that the decisions encoded in this implementation are probably unsuitable for other applications, and hence the need to keep adding more and more parameters and overrides.

      I think there’s a correlation with how functional programming and object oriented programming tend to be practiced too. FP libraries usually provide some abstract entity, which may be simple, self-contained and reusable in the first sense. Whilst OOP libraries often provide interfaces to some concrete entity, like a Web service, with hooks and parameters to make it reusable in the second sense.

      I think this may be a consequence of their approaches to code layout, the expression problem, etc. OOP limits what we can do (the set of methods), but subclassing makes it easy to override and alter how those things are done. FP limits what there is (the data constructors), but makes it easy use those things in new ways.

      1. 1

        Hmm. His goal and aim seems…. twisted. Short sighted.

        I look at the average industrial code base….. it’s been around a long time, and probably be around in some barely recognizable form even longer.

        CEO’s come and go like may flies compared to code.

        Extensibility is required because the code will be extended. For decades to come.

        Way way beyond the original design.

        Usually by programmers who are cursing short sighted quick fix shippit types with every breath.

        Re-usability is required, because if you copy-pasta and roll your own of every thing in the system…. you massively bloat the maintenance burden, inflate the bug count and decrease the functionality. Yup. Decrease the functionality. If I increase the functionality of a component in a well factored system I increase the functionality everywhere it is used.

        But beyond the obvious stated utility of extensibility and re-usability, they are pointers towards good code quality.

        Code that is easy to re-use is Good Code. (Note, I do not say code that is re-used is Good Code, I say code that is easy to re-use is Good Code.) Admittedly ease of re-use will encourage re-use, and re-use will also wear off the rough edges of bad code.

        Code that is easy to extend, is Good Code.

        Hint: You are always extending, and re-using code. The code base in the repo yesterday is not what it is today. It’s an entire new copy-pasta and tweak of yesterdays code. And yes, your old function has been re-used in todays.

        If you are never re-used and extending, Go Home, your Job is Done. Rest in Peace. Sign up for a Mac Job.

        The rest of us will keep shepherding our code bases, delivering more and new value every cadence.

        I guess I say back to him, “Yup kiddo, I’m in it for the money. Today, tomorrow, and next year. This isn’t a plastic bag to use once and throw away. Tend it well and you will deliver more and more value for decades.”

        1. 1

          Responding only to the title: probably that people don’t notice it exists.