1. 41
  1. 35

    Use a library or framework.

    So the best code is actually somebody else’s code.

    Use a third party SaaS tool.

    Somebody else’s code on somebody else’s machines.

    if you can solve a problem without doing anything, it is better to not do anything

    you don’t say…

    1. 24

      If I had to rank problems with modern software development, “devs don’t use enough third-party libraries and frameworks” would be way, way, way down the list. Much higher on the list would be “few devs bother to learn how to write code that can be reused without causing more problems than it solves”.

      Relevant: Designing and Evaluating Reusable Components (2004) by Casey Muratori

      1. 10

        I think this is a fair reply to the literal interpretation of the post, but wholly irrelevant to its spirit.

        Yes, using someone else’s code is still using code, but the important things are:

        • It’s code you don’t have to maintain and support (at least not nearly as much as code you’d write yourself)
        • It’s already done, so you save time by integrating with it rather than having to write and test it
        • If you pick a decent module/framework/tool, it’s likely the author has spent significantly more time refining it than you would if you wrote it yourself, as it’s the purpose of the whole module versus your need of the hour

        It’s also worth mentioning that picking which third-party code or tool to use and (more importantly) which not to use is a skill which gets better with experience. Those less experienced in making those critical distinctions are sometimes bit by bad choices, and revolve to reinvent the wheel.

        you don’t say…

        Regarding this, it may be obvious to you that solving a problem with little or no code is better than the alternative, but this is far from obvious to every developer.

        An outsized portion of developers, even experienced ones, are more oriented toward writing code than solving problems. I’ve seen more than one occasion where a developer starts down the path of designing a complex system to avoid asking a user to make a tiny, effortless tweak to their workflow. Asking them to do so is a win by every measure, and yet many developers fail to consider it.

        1. 9
          • It’s code you don’t have to maintain and support (at least not nearly as much as code you’d write yourself)
          • It’s already done, so you save time by integrating with it rather than having to write and test it

          These are both terrible assumptions. They can be true, but they’re by no means guaranteed. And if you do end up having to make changes to that third party code, it’s going to be a massive pain. Vendoring the code into your repo can alleviate some, but not all, of that pain.

          • If you pick a decent module/framework/tool, it’s likely the author has spent significantly more time refining it than you would if you wrote it yourself, as it’s the purpose of the whole module versus your need of the hour

          Time =/= Quality. Specific solutions to specific problems almost always outperform general solutions in every metric.

          1. 5

            Like I said, evaluating whether to use a library or to write it yourself is a skill. I hoped I’d made that clear in my original post, but those points are assuming you’ve done your due diligence in choosing a library. I’m not arguing that picking any old module will automatically save you time and it’ll just work effortlessly, but if you do that due diligence you can have pretty good luck.

            The project I work on at my job had a sizable number of dependencies and we spend relatively little time dealing with those downsides because we do a decent job mitigating those risks.

            Like everything else, it’s a tradeoff. Sometimes the odds favor writing it yourself, and sometimes they favor using someone else’s code.

            1. 4

              Totally agree. I just think the far bigger problem is devs piling on layers and external dependencies due to the belief that it will save them time or make their code more “clean”.

              There are very few truly general abstractions. Compilers/Interpreters and Relational databases are probably the two most obvious (in software). And they took decades to reach sufficient maturity to be the obvious choice over rolling your own special-purpose solution. And still, they come with a considerable complexity cost.

              1. 2

                Like I said, evaluating whether to use a library or to write it yourself is a skill.

                I think it’s worth highlight this, given the blog domain is called letterstoanewdeveloper.

            2. 1

              It’s already done, so you save time by integrating with it rather than having to write and test it

              I’ll add this is only true if integration effort is less than effort of writing and testing a solution. At first glance, it seems like it obviously would be. Many 3rd-party libraries will be more complex than one needs, have poor documentation, maybe miss corner cases, etc.

              I can’t give any guidance outside “learn from experience” on how to evaluate when you’re running into this problem. Lean, focused, and well-documented libraries seem to be a good pattern. Personal example for development server in Python was choosing Flask over Django since I figured I’d get working code out faster. It’s been working fine outside one problem that might not even be Flask.

          2. 6

            Fair points. I did mention manual processes as an alternative.

            I think some developers are enamored of writing code for code’s sake. I was when I was younger.

            Maybe a better title would be “The best code is no custom code”?

            1. 18

              Surprisingly often, there’s more work in gluing together frameworks than there is in just writing the code. And you lose visibility into what’s going on, so when it goes wrong, it’s much harder to debug.

              There’s a balance to be made. I try to restrict dependencies to ones solving hard problems.

              1. 4

                Surprisingly often, there’s more work in gluing together frameworks than there is in just writing the code.

                In my experience that is true for the golden path, sometimes. But once you, or your users, stray off the happy path, I find that libraries and frameworks help a lot. Yes, it’s less fun for me to read a doc and learn how to use a third party lib than to write my own, but long term the former is the better solution.

                1. 4

                  Glue code is rarely bug free, and commonly misses edge cases between what one library outputs and another accepts.

                  The libraries also get special cases wrong more than you’d expect. If I’m lucky, I can get upstream to ship a fix quickly. But often, I just need to work around it.

                  Popular libraries too: I’ve spent days dealing with issues in grpc, core Android APIs, and similar.

              2. 4

                It’s certainly valuable to re-use mature, maintained solutions whenever possible. I think we need a new metric to capture evaluate this. Maybe something like “Maximize annual maintenance dollars per Line of Code”?

                This encourages you to think through who’s actually maintaining the stuff you’re using. You can write it yourself and pay 100% of the maintenance cost. You can use an open source library and benefit from community maintenance investments. You can pay a vendor with a dedicated staff for maintenance investment. Somebody has to do the work or your code rots.

                You have to think carefully about your unit of analysis though. There are some LOC that matter more to your business than anyone elses’. Are those features actually benefiting from investment received by their parent libraries?

                1. 1

                  Great idea. I think you meant minimize, though?

                  1. 2

                    I was thinking in terms of maximizing the total investment in your code base, not necessarily your own investment. For example, it’s probably not a good idea to write your own Operating System. You can choose one that already has millions and millions of developer dollars invested in it. Sometimes you can get it for free! This lets you start way further ahead. The same logic applies to almost anything. Use stuff where lots of other people also care about making it work well, so you combine forces. Then focus you internal efforts on the stuff that really matters to your organization.

                    This is somewhat related to the Choose Boring Technology argument. You have to choose where to spend your resources, so you have to put them where they can do the most good.

              3. 6

                Ahem. Economics, Mr. Llama!

                So the best code is actually somebody else’s code

                They’ve already paid for it. You get to use it for free, maybe pay a little maintenance cost. Is that a good deal? Depends, but probably worth consideration.

                Somebody else’s code on somebody else’s machines.

                Infrastructure costs money too. Do you really want to be in that business?

                If you’re writing code for fun, great, have fun. But if you’re writing code to make money, I think it’s your responsibility to actually make some money. Or at least, not just throw it away merely because it’s more fun to reinvent stuff.

                1. 2

                  Use a library or framework.

                  Perhaps a library is a good idea in many circumstances if it is sufficiently well designed but frameworks can be a lot of trouble.

                  1. 1

                    I’m upvoting both you and the post on this one. The deep irony here is that you can say things like “the best code is no code” and seem trivial, trite, pointless. You’re just restating the obvious!

                    Everybody can agree, get a nice chuckle. Then they go out and write a bunch of code they didn’t need.

                    Profound statements tend to be facile as well. For me, folks kept saying things like this over and over again until one day the light went off. I’m not sure if I just had to wait until somebody said it the right way, I had to hear it X times, or personal experience demonstrated to me how much I said the words but didn’t actually live the life. Took a long while, though.

                  2. 11

                    With respect to use of third party libraries, I agree it’s important to be able to do a review of the space and try to adopt likely candidates where you can. But it’s equally important not to get stuck trying to make that work: it can become a kind of good money after bad fallacy.

                    Sometimes the libraries in a space are just of a poor quality. Sometimes they are at an inappropriate level of abstraction. When you look under the hood, it’s a large codebase that would take at least as long to understand to the point where you can fix it as it would to write a simpler more purpose built body of code for your own thing. The process of understanding a domain often looks not dissimilar to prototyping anyway. Plus, there’s no guarantee that the project team will accept your patches. In the limit, you’re committing to possibly maintaining the library yourself anyway, if the project dries up or changes direction – is it code you can see yourself maintaining?

                    Use third party libraries, certainly, but be critical and thorough. Don’t underestimate the cost of adoption, and don’t overestimate the cost of a less general piece of code you write yourself.

                    1. 1

                      “Sometimes the libraries in a space are just of a poor quality.”

                      When considering these things, one thing I thought about was starting out with a specification-based, testing strategy before adopting a component. You get the component, look at closely to determine assumed behavior, code that into specs/properties, do property-based testing, do some random testing, and watch what comes out. You’re codifying the expected behavior before watching if actual behavior matches it. Also, does either form of testing drop into weird, error handling? And, looking at example traces, does it look like you’d have a chance of easily debugging it?

                      This will take a bit of time investment. It might save a lot of time for components of low-quality, though. It also increases experience in using testing techniques that they should already be using on internal code. Nice, side benefit.

                    2. 5

                      Welp, there goes my motivation to finish the draft I have making the exact same point. Good post.

                      1. 4

                        If HTML can solve the problem, use HTML. Keep it simple, people. But, we’re never gonna survive unless we get a little crazy.

                        1. 4

                          I completely agree with this. What’s the point of making a custom website for an ecommerce of basic company website anymore for most people? There’s so many nice templates on services like Shopify and Squarespace. Better to just recommend those services for simple sites.

                          1. 4

                            Absolutely, in most cases. Personally I’m building my own ecommerce site because it’s fun and I can do it exactly my way without restrictions. It’s not economical sure, but I feel like I’m getting a lot out of it. Would I do that for a client? I’d have to be insane (I work with Shopify daily, it’s great).

                            1. 2

                              Exactly my thoughts! I’d code it myself if it were for my own stores, but seems like a waste of effort for (most) customers.

                          2. 2

                            A line I say a lot comes to mind:

                            “Features are assets; code is a liability.”

                            I tend to modify this to be more precise:

                            “Capabilities are assets; custom code is a liability.”

                            A lot of software is written with a large degree of uncertainty about what the set of end-users actually need. In the early days, custom code is a very expensive way to learn relative to using off the shelf tools.

                            So you want to build a form — let’s say an eligibility screener.

                            Building it with custom code usually takes a lot longer than an off-the-shelf tool, and the main things you’re seeking to learn (really core stuff to the form: what are the right questions? how do people respond to this or that phrasing?) isn’t supported by writing custom code.

                            So in those cases I almost always recommend an off-the-shelf form SaaS tool for alpha versions. You move fast, and the cost of change is incredibly low.

                            Once you’ve reduced uncertainty, you probably start to hit the limitations of that tool, so maybe you consider a framework, and mayyyybe you consider custom code. But, honestly, before that point custom code is just slowing you down and not helping you learn much.

                            I often say: “I’m very confident you can build a custom form later. Let’s figure out everything else by putting actual features in front of actual users and iterating fast, shall we?”

                            1. 1

                              This was a short and sweet bit of advice and I love to see it. I’ve read a lot of “the best code is no code”-style posts and was thinking of writing my own!

                              I ran into the what-if spiral though. To play Hacker News’ advocate: what do you do about something like the npm problem, where your project may have a single point of failure far away? And how do you vet a library that can possibly depend on a library… that depends on a library etc… that unknowingly sends tracking data over http? What if that’s not the case but could be the case tomorrow? Perhaps you can get really good at vetting libraries and their maintainers and their sponsors and…, but at some point isn’t it exhausting to do so? Because of this, is it counterproductive to advise new projects to rely on existing things more? (Maybe not – perhaps these problems are the cost of doing business?)

                              In other words – how do you get that type of person to realize that these issues don’t come up in practice?