7 ms·
(tangentially related to this article) I have recently come to realize that, at least in my world, source code older than five years is basically doomed. Deve
by liveoneggs 9y ago
(tangentially related to this article)
I have recently come to realize that, at least in my world, source code older than five years is basically doomed. Developers simply refuse to work on it.
The code that makes it to five years is extraordinary as most of it "dies" before reaching the eighteen month mark.
As a result I have recently been shifting my view to support replace-ability vs maintainability whenever possible. I'm not totally sure how to achieve it, though. Most current trends seem to be towards increasing baggage. (docker)
Data lives on and on and on, however. Data is king. :)
- akkartik 9y agoTotally with you. I've been thinking of it as rewrite-friendliness, and have some ideas for encouraging it: http://akkartik.name/about http://akkartik.name/about Even if people don't believe that all code over five years old is doomed, writing code to be easy to rewrite still seems like a useful idea. You're preserving optionality, you're making it easier to try out multiple designs, and you'll have an easier time recruiting collaborators because they'll have more fun projects to try, and so they'll be more likely to progress 'down the funnel' from using a project to hacking on it to contributing it all the way to taking over its running.
- billysielu 9y agoI love your website. My experience (web app for heavily regulated industry): - Customers don't want major versions to be continuously deployed. Each deployment involves validation and training. They want the software to be left alone, perhaps with the occasional bug fix. - The business needs new features to stay competitive. - So you're left actually needing to host multiple versions. All the major versions the customers are on, and want to stay on, and one latest-and-greatest version for winning new business. - Never force a new feature on a user. It becomes obvious that you're building things that most of your customers don't want. This means don't create a major version and automatically deploy it. - Moving data between systems is hard. Plan to never move data between systems, or major versions of the same system. Users prefer to see their data where they left it, looking exactly how they left it. A major version should be empty. If you constrain a new version of your software based on old data, sooner or later you're stuck, either because of schema or because of volume. - So if you have a big new feature, you save it for the next rewrite. - Once you've decided that at some point in the future you're going to do a rewrite, things fall into place nicely... - You avoid the situation where your dev team is mostly useless apart from the few guys who originally wrote the system. - You avoid the endless accumulation of data. - You avoid being commanded by the product team. - You avoid being hated by your users, and your clients. - You avoid spending huge amounts of time and money on things you didn't really need to do. - You avoid the end of your business, which is inevitable given ~10 years of 'current best practice'. - The part that I don't know yet is... developers have been avoiding rewrites for so long, we haven't really got good at it. We need to do it, do it often, learn how to do it well, and share that experience.
- icebraining 9y ago1-4 jibe with my experience.. that's why we built a SaaS cloud that allowed each customer (company, not individual users) to run a specific version of the platform, rather than the full multi-tenant model where everyone is on the same track. The latter may work for peripheral applications, but for core business apps it's a non-starter. Unfortunately, it often felt that we were having to write everything from scratch; you can barely find anyone talking about this model, or any tools designed to handle it. Everyone seems to be either fully multi-tenant or manually launching individual servers (which is not feasible for low price SaaS).
- taude 9y agoWe're in the same boat as you and our SAAS model involve custom deployment versions for each client. We're looking at trying to keep the databases unique per client, but handling the core requests in a multi-tenant environment, but it's difficult to plan ahead for all the different asks our customers need. I often wish I worked at one of the SaaS product companies that target small-business.
- icebraining 9y agoI've considered that approach, but that means keeping the code fully retrocompatible, and that kinda leads to madness :D Plus if you have different processes per client, you can provide better security, particularly in terms of leaking customer data to each other. In our case, we just used different Linux and Postgres users for each client, but even just that meant that a few security bugs discovered in the application couldn't be used to read/write data of other customers.
- BatFastard 9y agoYou have obviously not been a developer for very long. I commonly use code that is 20 years old. Of course that code is well maintained C and C++ code. This is one reason the not acquiring or correcting technical debt is so important for the long term health of a company. Now I agree that data is king, but if you have to rewrite you code base every 5 years you are doomed.
- sidlls 9y agoI've been writing code for over 20 years now, longer in the industry than in academia now. The trend toward using the latest, shiny new thing seems to me to have accelerated, too. I would like to go back to a job where I work on code that includes decades old C and C++. Unfortunately those jobs tend to pay significantly less than others I can get.
- BatFastard 9y agoI have used my share of shiny new things, I have created many shiny new things. But you can not build a society based on shiny new things. At a certain point the churn rate gets too high. A friend of mine is working for an internet security company that seems to have the enlightened attitude towards software, everything is test driven and the majority is C++ and Java. This code will be around in 20 years, and will bring in millions of dollars of revenue with minimal maintenance.
- sidlls 9y agoI don't disagree. I'm just saying the market doesn't currently seem to value that.
- sAbakumoff 9y agoApparently developers compare their sizes too.
- marcinzm 9y ago>Most current trends seem to be towards increasing baggage. (docker) I'd disagree, docker for example makes it easier to create infrastructure as code which in turn makes it easier to replace pieces of that infrastructure. Same with micro-services which allow you to eventually replace isolated pieces of your infrastructure. The more modular and isolated pieces of code and infrastructure are the easier they are to replace piecemeal.
- toomuchtodo 9y agoDisagree. Simplicity in unnecessary abstractions is still convuluted. Although, I concede Docker is the bees knees for local dev.
- pier25 9y agoI'm guessing the smallest possible chunk of code is a cloud function. Easy to rewrite, replace, and deploy.
- lmm 9y agoDocker is a step backwards in terms of how transparent/code-ey your infrastructure is - a docker container is very opaque and you easily end up duplicating things between multiple containers in slightly different ways, whereas e.g. puppet was much more friendly to DRY.
- andrewstuart2 9y agoReplaceability is just system-level maintainability.
- eloary 9y agoI believe the right way to go is to focus on library code. If the long lived code is to prove exceptional it has to do so by being grabbed and bolted on to the new thing over and over, and that tends to favor an approach of libraries that assume very little, don't have many dependencies themselves, and opt for simple/robust API over being efficient. The API user can always recode the API for efficiency in their use case while as a library vendor your ability to guess at hotspots is limited at best, and as a consumer one is always looking for a library that can be used easily and disposed of quickly. In effect, "design by placeholder".
- akkartik 9y agoThis tends to be mainstream opinion today: figure out the timeless essence at different scales, decompose it into abstractions, freeze their interfaces so that people can start relying on them, and so on. But it doesn't seem to have helped for forty years of trying to do it. The world changes too quickly, we aren't quite as good at designing libraries as we think, the world is filled with historical accidents in interfaces. With hindsight, it seems clear they were prematurely frozen. Rather than dismiss these observations as isolated cases of people not practicing good behaviors, I tend to see them as evidence that we should be creating libraries far more conservatively, freezing interfaces far more late in the life cycle, perhaps even decades late. If I'm right, we are also overusing industrial notions of assembly lines and division of labor. Libraries with non-trivial functionality take a long time to get right, and in the meantime they are produced more like guilds of craftsmen than factories. (Even if the products themselves permit factory-like operation at scale.) In that initial bake-in period we are ill-served by conventional metaphors of software components, building blocks, etc. We should be dealing more in vertically-integrated self-contained systems rather than plug-and-play libraries. More OpenBSD, less `gem install`. I've been thinking about this for at least five years, ever since http://akkartik.name/post/libraries http://akkartik.name/post/libraries. More: http://akkartik.name/prose http://akkartik.name/prose
- billysielu 9y agoI agree. It's especially pungent in JavaScript, in which the average 'JavaScript developer' is playing some perverse game of library pokemon.
- marcoperaza 9y agoI used to work on Windows and would pretty often edit source files that were written over 20 years ago, sometimes by the guy four levels above me in the chain of command, back when he was an individual contributor. I actually preferred the C and older C++ components, with no exceptions and manual memory and error handling, to the "modern" C++ components. I recommend Raymond Chen's blog, The Old New Thing, for some cool stories about how and why ancient Windows/Office components were written a certain way, and what the effects down the line have been. Among other things. https://blogs.msdn.microsoft.com/oldnewthing/ https://blogs.msdn.microsoft.com/oldnewthing/ What you're saying is probably more true in the web dev world.
- swsieber 9y agoHeck, I work on a web product, and I regularly work on code a decade+ old. None of the developers who wrote that code are around anymore, except for the heads honcho. It always surprises me when I go to use git blame to see code that old (going to git blame to get a better understanding of the purpose), and at that point it's was actually an svn commit I'm looking at. Fun times. It shouldn't surprise me that since the code from that time uses Hungarian notation.
- lj3 9y ago> What you're saying is probably more true in the web dev world. Any world in which OOP is the primary paradigm. Then again, I've seen truly horrid procedural code as well. Do you have any specific ideas on why the code you're working with seems to be the exception to the rule? Or is it pretty much all in that blog you linked?
- marcoperaza 9y agoA few things come to mind: - Windows is (mostly) a platform, not an end application. So you need... - Backwards compatibility. It is a pretty hard requirement, as one of the major selling point of Windows is that your existing stuff will keep working. Programs targeting 16-bit Windows from the early 90s still work on Windows 10 (though they recently removed the 16-bit subsystem from 64-bit Windows). I believe it's the same with Office document formats. You already have the code that handles all of the old APIs and functionality, so... - If it ain't broke don't fix it. The old code has been thoroughly battle tested. Obscure edge cases have been addressed. Bugs have been fixed over the course of many releases. There is no chance that your rewrite will avoid regressions, and you'll almost certainly introduce new bugs too. It's better to make necessary changes to the old code than to try to start from scratch. And... - It's a lot cheaper too. Joel Spolsky has a great blog post about rewrites: https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/ https://www.joelonsoftware.com/2000/04/06/things-you-should-...
- artursapek 9y agoThis is exactly why I roll my eyes when devs passionately argue in favor of "consistent code style" and spend hours of their lives manually linting their code. What's the point? It will be gone next year.
- Terr_ 9y agoDid you tell the developers of 10 years ago that? I deal with their surviving shit daily, in mission-critical software, even. Gone in a year? Hah! I wish! Not just naming conventions, or assignments in if-clauses, but files there the first indentation level is three spaces, and the rest are all four... P.S.: And because it's that old, the change-history of a given line can be very important, so it's too late to mass-reformat everything. So you either make the file uglier by mixing "standards", or you have to hand-tweak all your changes to match.
- alextheparrot 9y agoManual linting is silly, but having a linter installed really saves a lot of pain. Git diffs should not include unrelated linting changes.
- artursapek 9y agoAutomated formatting like gofmt is great, and I'm a huge proponent of it. But code is so temporary that it makes no sense to spend man-hours making it look pretty.
- dasil003 9y agoOne-off script sure, but for core product code I disagree. It's temporary in the grand scheme of things yes, but how many times will it be read before it is gone? Taking a couple extra minutes to clean things up and standardizing style pays dividends in readability, and traceability via git-blame, etc. Same goes for extended commit messages that explain the approach taken. It's not a question of sinking tons of hours into this stuff, if you're using good tools it just becomes the way you work. Could you gain 5% efficiency by just blasting out the ugliest code you can? Yes maybe, but if it's actively developed code you could easily cost future developers much more.
- mathattack 9y agoYou haven't worked in a large company. :-) Much of the code behind your phone, the train system, chain restaurant ordering and any paper bill you get is likely 10+ years old. These companies undertake 5-year programs to replace ancient systems, and the 5-year programs frequently fail, and run late when they don't.
- santaclaus 9y agoHell, look at the discovered/mdnsresponder disaster that happened with Apple a few OS releases back for a publically visible instance of this.
- JustSomeNobody 9y agoYup, been through a couple of those. What tends to happen is the very senior engineers get architecture-itus and believe they'll actually be able to create this wonderful, flexible architecture that will withstand any future req change. Millions of dollars later, it's tossed in the trash and the old system is still selling, but customer retention is so high a focus at this point to stem the tide of exodus that all the developers do is put out fires now.
- mrep 9y ago> I have recently come to realize that, at least in my world, source code older than five years is basically doomed. Developers simply refuse to work on it. What world are you living in? I work for one of the big 5 and 75% of the software stack features I use have been in continuously developed for over 5 years.
- dmoy 9y agoYea ditto, I just fixed a bug in some other team's 5 year old code cus it was breaking on some of my team's stuff. Beyond some ungainly test code involving counting byte offsets, it wasn't that bad. The fix involved dropping in some other 5 year code via a library and voila it worked. I get some of what gp is saying, some older stuff gets abandoned and not improved much, while other stuff gets modified so much that it's sorta like that "at what point does a ship become a new ship though gradual replacement of all timber?" question.
- xamuel 9y ago>not totally sure how to achieve it [replaceability] One of the most crucial keys is: make your code greppable. For example, don't treat OOP classes as a license to use generic method names ("add", "set", "close", etc.), or it'll be difficult to weed those classes out.
- majewsky 9y agoDepends. If you have a statically typed language, you can usually just delete the class and fix all the compile errors. With a dynamically typed language, your point stands and I very much agree.
- fa 9y agoXamuel, where did your old blog go? The one where you talked about Esperanto as a gateway language to get people over their fear of learning a new language? I try to cite it regularly but it’s offline and Wayback Machine is giving me lip. (Sorry to barge in on this thread, I hope it’s the most reliable way to get to you.)
- justicezyx 9y ago"replace-ability vs maintainability" They are the same thing...
- dejv 9y agoYou would be surprised how long lived some code is. I used to work on codebase that was started during 70s and currently working on codebase written around 1995 - 1998 and maintained until today. There is wast amount of code used daily that is decades old, especially if those systems are not user facing.
- taude 9y agoI don't share the same sentiment. I routinely see active code being supported that 10 to 20 years old. Granted, it's no joy to work on, but it does get maintained. I'm curious what kind of environment you work in where where most stuff stops being used after 18 months...
- kerkeslager 9y agoThis is a product short tenures: software developers switch jobs every 18 months on average, so they don't get to see the long-term effects of their decisions. This leads to decisions with big payoffs in the short term that come back to bite you in the long term. Some examples: 1. Pervasive, maximal frameworks that favor terse magic over clear explicitness. At first this allows you to spin up a website in a few lines of code, but years down the line you're spending all your time reverse-engineering a workaround for a bug in Ember 0.2 so you can implement the same functionality in Ember 17.3 when the controller that it referred to is no longer in the codebase and the naming convention for tying together models and views has changed twice. 2. 0.x versioned libraries which solve the problem you have today, but cause 100 problems tomorrow when the maintainer deletes the repo. 3. Global state, which lets you bypass having to pass data through to components until later when you want to have more than one component per page.
- Mathnerd314 9y agoGlobal state is actually a good model, see https://awelonblue.wordpress.com/2012/10/21/local-state-is-poison/ https://awelonblue.wordpress.com/2012/10/21/local-state-is-p.... The issue is more one of fragmentation; figuring out which file(s) / method(s) are responsible for some item of state can get to be impossible without a powerful debugger, and constantly changing frameworks / libraries don't help.
- marcosdumay 9y agoWhatever this article is talking about, it is not what most developers mean when they say "local state". For a start, one does not persist "local state", and this is a clear give-away: > state cannot be cheaply recomputed or regenerated like other live values The author seems to be arguing against a global state encapsulated into a tree of disjoint accessors. And his solution: > our programs become stateless logics manipulating a stateful substrate Is verbatim the FP-way of avoiding working on global state.
- Pica_soO 9y agoCongratulations, you are one short step away from realizing, that replace-ability for their own software is the least thing any company wants. There are many ways into the walled gardens, but none out.