1. 14
  1. 8

    Today I wrote a little table printer, you know, stuff like this:

         a     │           b           │
    asd        │ 4,434,341,321,312,321 │
    asdasdsad  │               443,434 │

    Before I knew what was going on I had added options to use +---+---+ instead of the unicode box drawings characters, options to configure the box drawing characters per-cell, a CSV output mode, and a bunch of other options I don’t need, and all sorts of methods and constants to set all of this. All I wanted was a simple table printer for a little program I wrote that’s a bit more advanced/nicer than Go’s stdlib tabwriter.

    I ended up removing most of it; it more than doubled the code size, and I don’t need any of these features. I suspect most people don’t. And if you do: well, use something else then.

    And I’m actually fairly conscious about limiting the scope of libraries and such. It’s so easy to get carried away.

    I wouldn’t really phrase it as “opinionated” though, but rather more along the lines of “this only solves use case X; other use cases are entirely reasonable, but not solved by this library”, although that doesn’t have such a nice ring to it. It’s fine to solve only 20% of use cases, and if you do it well then those 20% will be solved a lot better than with a much larger generic library/tool!

    1. 3

      I ended up removing most of it; it more than doubled the code size, and I don’t need any of these features. I suspect most people don’t. And if you do: well, use something else then.

      How about forking your code instead? Thanks to your simple and focused design, I can more easily modify it to suit my own needs.

      While your more flexible version had a better chance of solving my problem, I would have a harder time adapting it if it didn’t.

      1. 1

        This kind of goes back to the MVP philosophy. It even works with Open Source in my opinion.

        In fact, it works even better. If you publish a utility or a library that works for you, and people start using it, 2 things will happen.

        1. People will open Feature Requests against your code, saying “Can we have it do x?” You can then decide to take another look at that idea.
        2. Less often, some hero will come along and say: “I used your code and found myself needing to do x, so I wrote the following patch to have it do x. Can you merge it into your code”?

        Every time #2 happens to me, it makes my day.

        PS: Linux was the original example of a small opinionated software that grew this way. I would argue Ruby on Rails is a later example

      2. 1

        Clay Shirky called it Situated Software.

        1. 1

          It is an interesting issue that comes up often in code.

          I was making an interface for some middleware (testing out writing something to handle the incoming http request in node). The code I ended up writing for some flexibility was rather long, but as soon as I wrote it closer to the interface that most end up writing it as the code ended up being something like five lines long.

          I have been looking at the CanActivate interface in angular, which is a guard on a route:

          canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree

          Just look at those return types! This is a perfect example of something that went down a rabbit hole, but one that I think is pretty justified. You definitely want pretty much all those cases at some point.

          But where it becomes a real issue is when there end up being edge cases that the documentation isn’t specific about what happens. Although I am failing to come up with an example just now.

        2. 3

          I haven’t personally experienced it yet, but I think that this style of focus is ultimate needed for a successful project. In my opinion, it’s better to excellently serve a few people’s needs than mediocrely serve many people’s needs. Also, trying to design up front for so many hypothetical use-cases is a good way to not finish the project.