I think most programmers work in a similar way: imagine a problem, then decompose the problem into its constituent parts and attack those simpler, isolated problems.
The problem with a large codebase is that no one, not even the person that wrote all of it can fit the solution in their working memory. The tendency of programmers (who generally underestimate complexity) is to say: wait a minute, this problem doesn't require 10 million LOC, I could easily solve this problem in 250 lines of elegant Haskell.
There are situations where the legacy codebase is completely unsalvagable, but I think more often than not it's throwing the baby out with the bath water, except the baby is an engine that, while flawed, is generating business value.
The problem with a large codebase is that no one, not even the person that wrote all of it can fit the solution in their working memory.
I think this is what a lot of people - even some coders - don't understand about enterprise-grade software systems.
Quite literally no one knows everything about any such system - you have to take a systems approach, design for modularity, document like a graphomaniac, and expect constant rework.
Unfortunately, a significant number of those enterprise systems weren't designed for modularity, have little to no documentation, and receive almost no rework to minimize debt.
I'm living in one of those worlds now. Fortunately I get to build new systems right now and not work on maintenance of current ones, but the last thing I worked on was an impressive monstrosity.
The best part was that the project I was working on was only scoped to fix compatibility issues, so we had to re-create interface bugs that were fixed when we fixed the compatibility, because it would break the user flow for end users.
The comment you replied to wasn't saying how the systems should be, it's what you have to do when you encounter such a system. No modularity? Start breaking it into submodules. No documentation? Write some (while you explore the system yourself). No time to rework? Communicate the urgency of it to the manager. That's actually what the best of the best programmers do (I'm not one but I've seen some of them in action). This is where all the hard work is, not coming up with a new solution/framework/system every time pretending you're Linus Torwalds.
[deleted] · 68 points · Posted at 21:23:54 on April 26, 2018 · (Permalink)
[deleted]
[deleted] · 145 points · Posted at 23:15:59 on April 26, 2018 · (Permalink)
It's a good thing you can choose another high-paying job. Most coders in other countries don't have one in the first place, and switching jobs means months of not being paid only to land another job with mediocre pay.
You need to think like the person who writes the checks, not like the person who just writes the code.
Step 1: Think about why companies pay for your time:
To increase revenue (add features)
To reduce cost (reduce maintenance, reduce operating cost)
To protect revenue (fix bugs, improve resilience to failure, add features an existing client is demanding)
To protect against a cost (regulatory compliance, changes for legal, add missing-but-contractually-promised features)
You don't want to break up the code because it's a best practice. No one pays for best practices. You want to break up code because it will be easier to change and easier to find bugs.
Step 2: Find a section of the code (a file or set of files) that is both frequently changed and hard to change - or find a section that is both prone to errors and difficult to debug.
Step 3: quantify step 2. You should be able to say something like:
"Over the past 6 months, we've had to change X Y times. I estimate that the complexity of X has cost us Z days of additional time (% of feature development time). We are very likely to keep modifying this code. If I get H hours, I can eliminate this extra time."
Another pitch you can make is to correlate changes to bugs, like:
"Over the past six months, we've changed X Y times to add features. This caused B bugs costing D days to resolve. F upcoming features will require modifying the file again. If I'm given H hours, I think I can reduce the cost of bugs per change by % - saving us S hours of debugging over the next 6 months."
Have a way to measure this that you will repeat over the six months after modifying the code. It doesn't have to be incontrovertible, just probable - people who write checks are used to working with probable. Keep in mind that the less certainty your measurement has, the bigger your gain has to be (would you pay $10 for a 50% shot at winning $20? No. How about winning $50?).
Step 4: pitch it, then put your money where your mouth is. Make the changes, watch the cost reduce - or not. I recommend providing follow-up reports at 1 month, 3 months, and 6 months comparing projections to actual.
If you aren't confident that you can produce these outcomes, then you should not receive the time to do them. If you can produce these savings, then you should receive the time.
Note: there are good reasons why you still might not immediately get the time. If the company has to produce X changes within Y time and it won't be able to do so while also paying for your changes, then you won't receive that time. You can offer to reduce the cost by doing your refactoring as you make the next N changes, adding H hours to each change but still getting most of the results.
Higher-ups are frequently familiar with the fact that your changes are taking longer and longer and your bug rate is going up (often painfully aware, actually). If you can give them a why, what to do about it, and a way to see that you're correct or wrong quickly without having to pay for the full rework, you bring actionable knowledge. That's how you get your seat at the big table.
Source: engineering manager. I've been a having these conversations for a few years now.
pdp10 · 9 points · Posted at 21:51:39 on April 27, 2018 · (Permalink)
You have excellent points and I upvoted this post.
However, I feel the approach isn't sufficiently agile for a lot of shops, and the idea of making (what is nearly) a full-blown sales presentation in order to do my job fills me with weariness. It seems to require exceptional ability to plan ahead and to estimate, both of which are considered very difficult in the real world.
Only do this when you've been actively prevented from fixing something. Otherwise, the default posture should be to ask forgiveness, not permission, when it comes to your codebase. The same principle can be applied to operational change control, under proper conditions.
Only do this when you've been actively prevented from fixing something.
Absolutely yes.
Honestly, the best way to improve code is with every change. Every change should make that section of code a little easier to change next time.
Most of the time when people ask for refactoring time, it's a major refactoring. Most major, non-incremental refactoring is misguided.
The method I provided is best when you want to change how your company works - to convince people to that your new standard should be...well, the standard. It also works when you're prevented from taking time to refactor charges.
Besides that, though, it's a good skill to be able to reason in this way, to communicate in this way, and make promises in this way. I'd say the whole presentation is about 3 slides or a short email (problem w/ data, why the problem exists, proposed experiment). Reasoning about development in terms of business needs rather than programming best practices.
Of course, scale is everything. I've worked on two-person teams where it'd be as simple as "I tried this in my recent patch, what do you think?" I've worked on 100 person distributed teams that require a bit more communication overhead.
feenuxx · 15 points · Posted at 00:19:57 on April 27, 2018 · (Permalink)
Lying about it causing issues has been the course I’ve taken in the past. It’s a noble lie.
It's the hard part because we as programmers are usually not so good at working people. I had situations when I tried to do my best and failed, sometimes it works after some time and constant reminders. It's just I believe we are not here to deal with the shiny cool stuff, we are here to deal with all this crap for the most part. The fact that a person can leave something better after themselves than what they took over speaks a lot, and often they are not enabled by their company at all.
Of course there are crappy companies, and sometimes leaving is the only option. But in my experience 100% hopeless employers in this regard are less ubiquitous than it seems.
Proactive sprint planning and honestly pessimistic estimates. The "sandbagging curmudgeon" during planning tends to be "the only team member that nailed their tasks" in the retro.
You've got two feet, and can use them to walk away (ie, quit). Probably a last resort, although this is a pretty grand time for employees in our industry.
Why should they care? And by that, I don't mean that they should't - I mean understand why it would be important to the people paying for it, and that gives you the tools to convince them.
Did the last feature take 3 times as long as it should have because you didn't understand the code? Have you spent half your time in the past 6 months dealing with production incidents because the code is unstable and the logs aren't good enough?
If your employer has any interest in how long it'll take to deliver the next feature, they'll be interested in ways to make that delivery (and the ones after that) quicker.
"I want to document the code and move a bunch of files around" is quite rightly going to be met with blank states and a lecture about delivering value.
"I want to halve the time it takes between you coming up with the next killer feature and that feature being in the hands of the user" is going to get them much more interested.
What're they going to do about it? Fire me? I would love a three or six month vacation. But I know that it costs >$100k to hire someone, on average, into a position like mine, for companies where I live. Firing isn't cheap either. Letting your employee spend some time here and there improving code is way cheaper, even if you wish they spent 100% of their time on features.
Of course the truth for me is that my boss is a technical person, and my boss's boss, and my boss's boss's boss, and so on. They all understand the value of spending a bit of time improving things under the hood, and wouldn't think to hassle me about it, so it's a moot point.
I'm willing to do it I just have no agency to do so.
One approach is just to improve things as you go. You don't have to ask permission to write a for loop, right? Similarly, as developers, we don't need to ask permission to pay down technical debt. We just do it as part of our job. If you're being micromanaged to the point where this isn't possible, well, look elsewhere.
Also, if you're working 60 hours a week...please stop doing that.
pdp10 · 1 points · Posted at 22:01:24 on April 27, 2018 · (Permalink)
I generally agree, but it should be noted that there are houses where official policy is to keep diffs minimal. Either for understandable but possibly misguided reasons, or because of less understandable diktat from principal.
Put it in return on investment terms? By spending 10 hours fixing this now, you won't have to spend 20-30 fixing it later. It's cheaper in the long run to fix things now than to lose money while trying to fix them later. Helps if you can document bugs and downtime due to these issues.
sroasa · 3 points · Posted at 00:00:18 on April 27, 2018 · (Permalink)
I think you haven't worked in enterprise-y environment or similar. The legacy code is one big of a mess, and to rework that into submodules need, well, rewrite. It may be so big that it takes hours to days to weeks even to modularize the smallest subsystem (oh man the jargon). And managers don't like that. They love small man-hours tasks to do some enhancement, no matter how you hack them.
And what's worse is, there are no or useless documentation. I couldn't care less about technical documentation, at least you can read code. But they also don't have business documentation, and any person in charge doesn't know any of the business process. They rely on how the system work right now, so it's hard to do even the slightest modification, because the risk is really high.
And making the management agreeing to do a rewrite may be beneficial, that they can start to define the business flow and test cases, managers start holding responsibilities for business flow, testing and bug fixing timeline will be longer, which you won't get any in normal flow.
z500 · 1 points · Posted at 14:00:41 on June 2, 2018 · (Permalink)
As if we had the time to make the codebase less shit, rather than just shoving features out the door.
[deleted] · -3 points · Posted at 21:13:16 on April 26, 2018 · (Permalink)
We were forced to burn our documentation. Design and program design was taking too long. So our director decided that it all had to go. He figured if we went directly to coding we could save 70% of the time.
metis2 · 1 points · Posted at 06:28:13 on April 27, 2018 · (Permalink)
Also, I've seen enough sales men offer handing over code as part of a sale knowing full well that code was worthless with out the original programer
GBACHO · 2 points · Posted at 06:13:33 on April 27, 2018 · (Permalink)
Documentation is also another bit that needs to be parsed. It may be out of date with business requirements or code. There are definitely situations where documentation is a hindrance. The truth is always in the code. Documentation is what someone wanted to truth to be
So true. My company, our application was mostly written by an offshore firm (I was hired as a part of the process of moving development back to the US). The code is partly modular, but mostly tightly coupled, and in some places is a complete mess. Most of it is maintainable, but there are pieces of it where the codebase is so horrible most devs on staff are afraid to touch it. When I started I was super cocky and made it my mission to take on all the challenges there... Let's just say I no longer do that anymore. Too painful to deal with.
Our general approach is maintain as best we can, but periodically we find time to do a complete rewrite of certain pieces of the app. Not the whole thing, but parts of it that don't just have bad code but actually work very poorly, where it is worth the effort.
Exactly this - devs hate other devs and other devs code for exactly this reason - it is super hard to read and understand all the brainfarts that other dev had while writing the code. Lack of documentation, lack of proof that the code works and that it does all the things that it should do, it all drives us to just dump all the code in toilet, because it would take longer to understand all the mess than to write your own code.
[deleted] · 1 points · Posted at 10:59:29 on April 27, 2018 · (Permalink)
Which is why the real problem with software is just that you get what you pay for.
Enterprise software is built for enterprises that don’t want to pay for testing, documentation, system architecture, refactoring....
Serious question, how do you document these systems? What do you document? Documentation is my hardest area, I don't know what the next dev will want to know.
[deleted] · 85 points · Posted at 21:29:32 on April 26, 2018 · (Permalink)
Explain the purpose of each class/method. Walk them through how your code works. Explain why you choose the implementation that you did perhaps by listing pros/cons of the alternatives. Try to break large methods into smaller well named ones. Name variables clearly, avoid excessively long expressions, avoid obscure ways of doing things(like the xor swap for example). Readability is always preferable to a few saved operations, so pick readability when faced with this choice. Try to keep code modular, it's easier to understand that way. Methods/classes should "do one thing and do it well".
I should have been more clear, what I currently do:
Make sure method names convey what they do
Follow basic command-query-seperation and seperation of concerns so reading is easier
Name variables semantically
Add comments where something seems obfuscated in complexity
Add (language specific) comments to methods that show on intellisense describing what it does and it's parameters
I'm good at documenting things piece by piece, methods, variables. I'm bad at external documentation describing how these individual pieces work together to do something. I know how they work, I can write it out, but I always end up writing a novel instead of something easy to digest.
Maybe what you're working on deserves a novel. If it's clearly written and everything spelled out, reading that is significantly easier and more helpful than terse documentation.
It's kind of like dissertations versus conference papers - I way rather read a dissertation where they took all the room to explain every last detail than a conference paper trying to pack all their contributions in a small page limit even though the dissertation is about 10x longer.
Majority of folks dont want to read a tome when it comes to documentation. If it looks too big to digest they will probably not read it at all. The code should be self documenting via clear class and method names. That way when you change code there is no documentation that needs to be updated. The only time comments should be necessary is explaining WHY something was done. Otherwise the "what" of the code should be able to be followed from the code itself.
In terms of documentation I think class relationships would be a good candidate, I.e. A diagram showing said relationships in an easily digestible format
Even good self documenting code is harder to read than someone's explaination of it. Thinking it's not is how we end up with so little documentation and everyone preferring to start over. If every codebase I needed to modify/maintain came with a nice tome, I'd be ecstatic. Especially if it was neatly organized, had a nice introduction chapter, and then chapters for each subsystem. No one is gonna read it cover to cover, but going to the relevant part and having everything I need to know right there? So helpful.
As for why? Class diagrams to me do not tell me at all what the person was thinking when they did X. I don't see how they help answer why. Class diagrams are super useful for what exists but you said this documentation should only answer why - which is usually done a lot better in writing in my experience.
bhat · 11 points · Posted at 22:10:24 on April 26, 2018 · (Permalink)
The most powerful concept in computing is abstraction: being able to hide the complexity of a subsystem or layer so that it's easier to think about and work with.
So maybe the abstraction is leaky (details that are supposed to be hidden need to be known outside the subsystem), or else the boundaries between subsystems aren't ideal.
taresp · 1 points · Posted at 14:57:39 on April 27, 2018 · (Permalink)
Provided it's done at the right granularity. A lot of times too much abstractions makes some fairly simple things hard to think about and work with. You can easily take a problem that originally fit in your memory and blow it up with abstractions to the point where there might even be less code, it might be more modular and flexible, but you can't see it as a whole.
Kind of like the idea that early optimization is the root of all evil I'd be tempted to say that early abstraction is almost as bad, but I guess it's really on a case by case basis.
There are really two audiences for your documentation:
people who want to use your function/library/class
people who want to change your function/library/class.
The former do not want to know the details of how it works. They want to know how to use it, the inputs it can cope with, how it handles edge cases, how it performs, and when it is appropriate to use it.
The latter are the people who need the tiny internal details.
A common strategy is to put the documentation for "users" in doccomments (which eventually end up in generated reference documentation, or a readme), and documentation for "modifiers" in the implementation itself. You might end up with an explanation of usage as the doccomment, and the function implementation starting with a largeish comment explaining how a fancy data structure works or something
The high-level goal is to allow people using your code to solve their problems without having to think through all the details of solving the problem your code solves. If your documentation forces the user to read their way through the thought process needed to solve that target problem, you've failed to abstract properly.
I've personally gotten much better at architectural diagrams. I always start there. If I can't conceptualize a simple diagram, then I haven't broken the problem down well enough yet.
Then my documentation starts with the diagram and the contracts ingress/egress. Pick a piece of the diagram and it should point at more specific documentation. Some times there's further diagrams, but eventually you'll get to API documentation.
I think the most critical thing is that code comments are a last resort. The primary audience for my documentation is the Product Owner and Consumers. I tend to only free hand comment on code when I can't reasonably fit the documentation into a higher layer.
You say you write a novel, and the thing is, I think that's the right track. I believe narrative descriptions of systems are a critical piece of sharing knowledge. The part you may be getting stuck on is editing: the real meat of the work of a writer. Chances are your "novel" is full of great insights and useful data, and if you could develop a clear strategy for laying it all out, and make it pleasant to read, you'd end up with something valuable.
I was just recently rereading parts of "Writing with Style", a short, excellent book on the art of expository writing. Maybe check that out and see if any of it resonates.
vcarl · 1 points · Posted at 03:14:22 on April 27, 2018 · (Permalink)
One point that I haven't seen in the replies: sometimes writing is the wrong medium. If you've written a novel, could it be communicated as a diagram, or a cartoon, or a talk?
There are also ways to improve your technical writing skills, which is definitely a skill in itself. Know your audience and what they hope to get out of it. Remove fluff and filler, give different levels of explanations at different points of the documentation. If there were a simple answer to "how do I write better documentation?" then there wouldn't be so much terrible documentation. I love this tweet from Kent C Dodds about how to write a good readme: https://twitter.com/kentcdodds/status/976813153647394816
Just to add: something people often fail to do is to specify the goals and specific non-goals of a particular class or function. This can lead to someone later "fixing" it by adding defensive checks for something that you really wanted to assume as a precondition, or by mutating what a class represents in a "useful" but ultimately problematic way.
It's also worth learning in what situations "tradeoffs" for readability vs. speed actually aren't tradeoffs because the optimiser is doing it for you. I've met many people who vastly underestimate the capability of a modern compiler, and end up believing they're making a speed/readability tradeoff in situations where they're not: both options end up as the same instructions. Common instances of this include division by compile-time constants (which some people like to explicitly replace with shifts or fixed point reciprocal multiplies) or function calls (which people routinely seem to forget get inlined).
Obviously, if you're using a scripting language or something this doesn't apply (modulo JIT, if present), but if you're using a scripting language and you care about micro-optimisations you probably shouldn't be using a scripting language (or you probably should stop caring)
Exactly this. Too many people think they're playing code golf at work. The problem with that is that, as this article mentions, reading code is harder than writing it. Another article, I think by Joel, also explains that debugging code is harder than writing it. If you write the most complex code that you know how to, then you won't have the expertise to debug it when it breaks (and it will).
In most cases, the method name should tell you that. updateAccountBalance() should be updating the accountBalance and you shouldn't need comments for that. They'll at best be redundant and a waste of effort to produce, and at worst they'll be or become wrong.
Comments are best used sparingly - tell us the thing that the coder can't obviously figure out from the code - that you picked this particular sorting algorithm because the distribution of key fields is skewed in some odd way; that you add 2 pixels and then take 1 off because of some obscure bug in the version of IE that your company uses in the Italian office; that you've no idea why this works, but it does and everyone who's ever tried to refactor it has brought down the server etc.
Hard to say precisely without knowing what you're working on, but for my work, I LIKE all of the below, though I usually have to settle for just most of it due to customer constraints or what have you.
A continually updated overall architecture diagram - literally put it in your version control if you can
Ditto data flow diagram
Functional block diagram (especially for OOP)
Actual commit and release notes, not just "fixed a bug"
Issues in the issue tracker tied to lines of code
Notes describing in English what you're doing when you're working on major changes like a refactor or a new feature
Either well-named folders in your code base, or an easily found document explaining what each folder contains
People tend to over-emphasize comments, IMO, not that you shouldn't use them, but they should be helpful detail backing up higher level conceptual documentation that helps the next devs find the files or code blocks they need to look at in the first place.
These are great suggestions. Once I'm in the code, unless it's a real mess, I can figure out what a function does and what it returns and what it depends on. Finding my way to that first function, however, can be an ordeal.
Been making great use of our internal wiki lately, and it's a game changer.
Using Confluence for documentation means, invariably, that the documentation grows into a horrid mess. Wikis can be used well [for documentation], but Confluence?
Part of the "horrid mess" phenomena is, I think, that there's a pretty big difference between the technical writer mindset and the developer mindset, and Confluence is often embraced [in part] to allow management to push documentation on the developers... except that with all the time-pressures they often miss out on the needed "context-switch".
Well, I'm the project/program manager, so I get to make suggestions. ;-)
xcdesz · 4 points · Posted at 04:04:48 on April 27, 2018 · (Permalink)
Take a look at the README files on some popular GitHub projects and copy what they are doing. README's and code/api documentation are really the only things that are useful to other developers. Put down everything you know -- it's a README -- you won't find a project manager nit-picking your words for political reasons.
Don't use anything fancier than a text editor to document. Anything that goes into a Word Document or Powerpoint will often wind up in Sharepoint and never be seen again.
a) what does it do,
b) how does it do it, and,
c) what the fuck were you thinking?
What he really doesn't want to know is the history of the development. Seriously, stop jacking off in the webpage. Tell me what your package is, not who made it or why. Put those things four layers deep in the "about our egos" page.
You’ll have architecture documents that describe how everything works at a high level along with the audience and use cases for a system and then functional specifications for particular features. There may be testing specs also that describe what is to be tested and how. If you hand those specs to a developer, they should be able to implement what is described. A technical writer may also use these documents to describe APIs, limitations, requirements and even usage examples to customers. When you see a public API - it has probably been documented in a specification somewhere even if it is a code generated API.
So it’s safe to say that several audiences will be looking at the documents. Data structures, APIs, unusual memory management, multi-thread, multiprocessor issues should be noted and explained. Limitations, dependencies on other features and restrictions should also be clearly noted. Large enterprises may have standards for naming and file structure, prefixes and the like. Those need to be noted somewhere and if the structure is non standard that too should really be described. If there are performance requirements, hardware or character set requirements, those need to be in the document.
The bottom line is, the more detailed accurate the document is, the easier it is to implement and the easier it is to debug if you are new to the code. The spec drives the implementation - not the other way around. You aren’t documenting a feature after you have implemented it. There are too many people involved to code sling like that.
Well there’s more than one way to do things, that’s for sure. But if you’re rolling out documentation to customers and other engineers, if you don’t have some kind of document, all that know how is trapped in an engineers’ head - how is knowledge debated and transferred efficiently and accurately to people not in the room? My experience is that these documents are quite helpful as it represents the settled architecture and implementation and can be read by normal people. Now maybe the form is different for others- a wiki, or whatnot, but that’s just formatting. All documents that aren’t code generated have a problem of rot if the documents aren’t maintained.
I’m sure that there are forms out there that write first and document later, if at all. That doesn’t work well if 2000 engineers downstream are trying to use your code, but is perhaps fine in smaller groups that communicate well.
And I’ve worked with groups with no useful documentation. I didn’t stay there long. The code was just as bad.
I definitely curious as to your philosophy. I have heard of firms that build delicate equipment that have huge documentation requirements to verify it does what it’s supposed to do. Parts for rockets and the like, for example. Way, way, more documentation than I ever had to write. So there’s all kinds of styles.
Basically what I teach my customers is moving more towards a DevOps agile world.
The first step is to start adopting microservices. Start with a new greenfields initiative and leverage Kubernetes (or Service Fabric for .net teams) and architect your application in such a way that it’s small discrete domains.
Once your first few teams get familiar with microservices and orchestrators (which really are the glue that holds everything together), start breaking development teams up into smaller pods that own the full lifecycle of that application. Smaller applications means faster development cycles, less complex documentation, and safer release cycles since there’s not a lot of fear of taking down the entire system with a bug (assuming its architected correctly with circuit breakers etc).
Once your teams are familiar with this concept, start building in a lot of automation and start coding in a more agile way. Develop blue/green or canary testing since you now have the platforms in place to support, leverage automated build tools, abstract away the Ops in DevOps as much as possible.
Now go back and build a facade and start slowly migrating your older applications into this new pattern.
Documentation is still important in this world, but by breaking down code into smaller manageable services is becomes easier and also less critical.
High level architecture diagrams and process flow diagrams are still important, but everything else is captured in your epics, features, and backlog.
Also the more automation you adopt the more automated documentation you can do, and the quicker you can react to change when your customers demand it, keeping your documentation up to date. Swagger is a great example of this.
I always have a disclaimer though - Agile and DevOps is not suitable for everything and anything. Use the right tool for the job.
I'm in the same boat. And I'm of the understanding that the entire agile philosophy works the opposite of the above post. Doesn't the whole "requirements are king" idea lead to all the problems associated with the customer not really knowing what they want and change being super difficult to implement when it arises?
Agile is a different approach. But if you have thousands of developers working on a piece of software, you aren’t making complex changes without getting a lot of experts involved - sometimes in multiple time zones and divisions. Agile doesn’t really apply.
Agile does a lot better when the problems are simpler and time frames are a lot shorter and everyone is close by.
For large complex projects this is where micro-services or SOA patterns come into play, which also solve the problem that you’re talking about. Platforms like Kubernetes combined with docker do a lot of the heavy lifting so smaller teams can work in a more agile fashion on large complex systems. This is how the tech giants do it at large scale, and they’ve democratised their orchestrators to make it achievable for the rest of us too.
Agile can and does work on large scales though. One of my customers (a bank) has 7,000 developers working on “more or less agile” with some tweaks.
ThoughtWorks also does agile successfully at a global scale. I don’t work for them but I know how they operate.
The point is really that there is a fundamental gap between the business and the technology that is best bridged by getting something into the hands of the business ASAP. Because wasting too much time on non-development outputs (like a SRS) is effectively a waste of time and money.
And in a lot of cases it’s true. I’ve had customers who insist on the “Big Design Up Front” way before and spend hundreds of thousands of dollars on design and documentation, only for it to change dramatically sometimes before the actual development even begins. A lot can change in six months, especially if you leverage the elasticity of the cloud.
Then when the users finally start using the application, and it doesn’t work the way they expect, I’ve seen entire rewrites.
Of course there’s always exceptions - legacy banking systems, medical platforms, safety systems, military systems, etc.
Anything that doesn’t really have a user interface, is mission critical to a countries infrastructure, is fairly static, and potentially has a lot of dependencies on a lot of legacy systems, are not usually a good candidate for “full” agile.
p1-o2 · 2 points · Posted at 08:42:49 on April 27, 2018 · (Permalink)
Can confirm. Micro-service architecture for enterprise is where it's at for keeping the concerns of the software loosely coupled. Agile can work well if it's implemented correctly and has the architecture to support it. Documentation doesn't have to be a waste so long as it's well constrained just like the code.
One thing, I really like, when it's documented, is things, that you, as the implementer, had trouble with. The API needs a special value, that isn't directly obvious? You thought carefully how to structure your loop? Those things are invaluable for someone trying to understand the code, as they can only guess, why you did something. Often people document, what the code does, but that should be obvious, when you name your variables, functions and types correctly. When it isn't obvious and you can't refactor, to make it clearly understandable, document it.
This only documents the code, but as applications grow larger, having documentation, that gives you an overview, is pretty important. At a certain point applications become to large to fit in ones head. Documenting the larger modules, where they can be found, how they interact and how their interfaces should be used, reduces the amount of information every developer needs to keep in their head, as they can view other code as a black box, that works as specified (until it doesn't, but that's a different problem).
Also start writing documentation early. None wants to document stuff and often people don't go back to document thing, when they are done making their changes, so get in the habit to document early. Also it can be useful to update/write documentation, when you have to understand a new system/module, as you are in the seat of someone new looking at the code, so you have a better idea, of what needs to be documented and it helps to understand things, when you have to think about, how to explain it to someone else.
For every hour I spend actually writing software. I spend at least another hour documenting. That includes:
Comments in the software: Comment blocks at the beginning of classes and all methods. Additional comments pepper through the code to provide insight into what the hell something is doing.
Jira Issues: Every line of software and every change is traceable back to a ticket. That ticket can be: a bug, an improvement, or a new feature. A ticket lifecycle:
submitted
reviewed
if recommended, opened and assigned
resolved
ready-for-test
passed (hopefully)
closed (after customer acceptance)
Git Version Control: We have git rules in place that will not allow any commits unless the commit message is formatted to indicate which Jira issue is being addressed.
Confluence: Is used to plan software releases and coordinate team members
We also maintain several documents:
Full Regression Tests
Release Specific Tests
User's Manuals
Interface Control Documents (for external system we talk to)
A Processing Manual which goes into fine detail concerning the inter-process and inter-thread relationships.
documentation is out of date before you start writing it. Static documentation is only ever necessary for government work or legacy work - like building planes or something that last 30 years and need really really old stuff that wont change by design.
For everything else document your one pagers and initial design to get buy off and money and never look back.
IMO you write documentation for modern fast moving software to get a promotion from management that cares about documentation - the key is to write the documentation outline - that everyone else should follow! - and then document your own stuff that you understand with it.
Sell it to your boss - get a promotion - and then watch everyone else groan that they have to document their stuff or follow some new business process. Meanwhile you look great for being the only service with "proper" documentation.
Be sure to get your promotion before your documentation is out of date and your stuck with your own business process. Let someone else kill your business process while you already got the glory.
And the users are worse. They describe a problem and expect some sort of answer on the spot. I've never heard of the field your referencing and I don't know where it's sourced from until I look. I get it, it's an error that could cost us millions but I still need to look first and getting my panties in a bunch does nothing but make you feel better because I share your concern. I deal with these problems hourly so no it's nothing new and nothing to get upset about.
The pattern I see is a developer gets a ton of respect in the beginning because they can get shit done super fast but eventually they hit the point your describing and need to start reverse engineering because they didn't document or put any focus on best practice. The president they set puts them in a tough spot and they get driven out of the job. The next developer comes in (and probably got themself into this same spot at a previous company) so they refuse to operate that way. Executives are stuck so they have to give a little more leeway and things start to get done right but there isn't time to fix everything, just what needs repair. Eventually things come to another pressure point and the company hires a consulting firm which results in enough manpower and drive to actually get everything fixed. At this point it's 50/50 if the lead dev stays but it doesn't matter anymore because it's best practice and any med level dev has what they need to do their job, management understands the need for documentation and best practice and now your a big shop that cuts the bottom 2% of employees on a yearly basis.
The issue is, this is often suicide. If it is always possible to fire the person who wrote the code, then there's no bargaining power except that they do good work.
Quite literally no one knows everything about any such system - you have to take a systems approach, design for modularity, document like a graphomaniac, and expect constant rework.
There's a word that non IT based businesses have stolen from software engineers, 'agile development'.
In my experience, documentation quickly falls out of date, aside some high-level stuff. I trust reading the code (and hopefully relevant and useful) comments over any diagram or something not connected to give warnings during the build process.
I agree. I feel I document well, but when I approach a new project I don't fully trust documentation if it isn't tied into a build process. Too easy to overlook and it's not the source of truth.
Swie · 197 points · Posted at 15:16:11 on April 26, 2018 · (Permalink)
Right. The sane approach to this is to identify exact parts of the problem that you don't like, and fix those, one-by-one, keeping in mind the others but writing modular code so fixing one part doesn't break the entire system or require a cascade of giant changes. You should have well-defined interfaces between parts so you can keep the same interface (or make minimal well-understood changes to it). If you don't have an interface the first step is to create one.
I do this regularly on my current project, I've worked on it for 5 years now and can identify bad design choices from the past. The solution is to, when an opportunity presents itself (for example, new features or bug-fixes), take time to make changes to the architecture of that part of the code.
Also when making changes you should have justification for it (future-proofing or simplifying the code is a valuable justification). That way you know it's not a vanity project because you have to actually be able to explain to people what exactly was wrong, and why.
I think part of what makes good programmers good is that they're not afraid to attack hard problems. A certain amount of irrational optimism or fearlessness is, at least for me, a helpful attribute. If you find yourself saying "how hard could it be" a lot, this is probably you.
You just have to be self-aware enough to know that your optimism is actually a productive form of delusion sometimes.
Larry Wall is famed for saying that three virtues of programmers are laziness, impatience, and hubris (relevant text is at the end of the article). Laziness means you only want to do things once ever; impatience means you don't want to wait for someone else to fix the problem; hubris means you think you can do it better than anyone else.
Absolutely. I get frustrated at programmers who throw their hands up at things too fast. Recently at my (quickly-growing) company, we've been trying to divide up responsibilities for different parts of the app, but some of the leaders of other teams will say "but you guys are the most knowledgable about X". And my response is always "nobody explained X to me, I went in there and figured out how it works and that is why I'm now expert on X. Your team can do it too - I'm willing to help, but you have to put in the effort". Rant over haha
I agree with what you're saying, but it also subtly hints at a key problem: the number of times I've had to "just get in there" is kind of ridiculous. We don't put enough emphasis on good technical documentation generally these days.
Ever see the documentation for things like the Apollo flight computer system? It's masterful! Everything explained, in words and not just diagrams... lots and lots of details. Looking at the code itself is almost an afterthought because by the time you see it, you already understand it.
Nowadays, we throw around terms like "self-docunenting code" and we say things like "the code is the only source of truth" and those things are certainly based on sound thinking, but we seem to think it's ALL you need. It's really not.
Imagine a new programmer on the Apollo program being told "just get in there" and explore the code. Somehow, I doubt that ever happened.
We need to write good, self-documenting code - and then we need to go properly document it anyway. Nobody should ever have to understand a system just by trying to decipher the code because for the reasons Joel talks about, that's hard. It IS the final source of truth, that's true, but it shouldn't the ONLY source of truth.
XANi_ · 5 points · Posted at 08:51:40 on April 27, 2018 · (Permalink)
Well I bet Apollo didn't have non-technical manager pushing for impossible deadlines.
And if your argument can be backed by "someone will die if we fuck that part up, in a big, expensive explosion" I bet people tend to listen more carefully
someone will die if we fuck that part up, in a big, expensive explosion
For real! There is a massive difference between trying to make a lot of money and trying to send living beings to outer space. Writing legible code is the most straightforward way to help out those who come after you, including your older self.
Fair point. But then again, maybe if we pretended we were all trying to keep rockets from exploding we'd do better work as an industry on the whole, 'cause right now we're really not. We fool ourselves because we've learned to make systems that somehow do the job, but we ignore all the warts under the covers that gets us there and we think the ends (it works) justify the means (it's not documented and is written poorly).
Code that isn't maintainable isn't good code at the end of the day, whether it's launching rockets or processing beanie baby purchases online (even if the potential bad outcome isn't comparable).
XANi_ · 3 points · Posted at 19:19:27 on April 27, 2018 · (Permalink)
Well it is definitely a good attitude to have. But it takes a lot to push it. You pretty much have to be in "position of power" (at least be one of senior programmers in the group, if not architect) to push for it, and you pretty much have to have at least some support from management (at least enough for them to not just fire you).
Current methodologies aren't exactly very useful for it either
True, and it's really that later point about management support that matters. I say this as someone who has been in a position of power for many years. I've definitely managed to affect some degree like I'm talking about, but I've never had what I would consider "proper" management support... not fully at least... so there's only so far I can move down the field (and honestly, management sometimes gets more blame than they even deserve: they have to make hard choices about what's going to be best for the business, and sometimes there's no choice but to think tactically, and that's when it's so very easy to allow standards to be pushed aside in favor of expediency). It is, as you say, largely a consequence of modern methodologies almost institutionally not allowing for it anymore.
Ah well, it DOES keep us employed anyway :)
XANi_ · 1 points · Posted at 22:44:56 on April 27, 2018 · (Permalink)
To be fair, you do not always know if a given piece of code will be even used in 6 months or in a year so trying to get everything to same high standard can be a huge waste of time.
Of course, if a given component does survive that long there is a good chance any maintenance or refactoring on it will be net positive but likely response from manager is "well it worked for a year, why need to work on it now?"
I'm in... "interesting" place where I am hired as a sysadmin but do that around 40% of the time and rest is mostly programming (mostly automation and integration of various systems, other guys in departmen do more of sysadmin stuff) so in a way I'm my own manager when it comes to programming and honestly almost every single time I decided to spend some extra time even tho it already "kinda sorta worked okay", it was worth it.
But that's a perspective for systems that usually run at least years (and only get upgraded, not replaced) so I already know at the moment of writing that it will probably be used for a long time. That isn't the case in a lot of software projects.
pdp10 · 1 points · Posted at 22:26:08 on April 27, 2018 · (Permalink)
Apollo had three deaths, which slowed down parts of the program. Maybe those deaths led to higher standards later.
[deleted] · 1 points · Posted at 10:54:18 on April 28, 2018 · (Permalink)
Well I bet Apollo didn't have non-technical manager pushing for impossible deadlines.
You’ve heard of the Space Race, yes? Whatever else the Apollo program had going for it, they were under enormous time pressure.
And if your argument can be backed by "someone will die if we fuck that part up, in a big, expensive explosion" I bet people tend to listen more carefully
People did die.
tcpukl · 1 points · Posted at 11:43:02 on April 27, 2018 · (Permalink)
Apollo missions are critical systems. The same as a nuclear power station. They also have formal proofs they work too the design spec. You can't apply the same to business software. They are just too big and often doesn't even have a design spec.
You said two things there that are interesting to me... first, are you saying that the control system software for a nuclear power station isn't bigger than most business software? 'Cause I would disagree with that (though I'll concede it's true for the Apollo software). Not really a big point though I suppose.
The second thing is thatbusiness software often doesn't have design specs, which is true (nowadays thanks to Agile anyway), but I would ask: don't you see that as a problem?
We've kind of gone down this rabbit hole over the last maybe 10 years (and I've done it in my company over roughly that period so I know full well how it is) where we do exactly as you say, and I often times wonder if people really understand the consequences of that path. Rapid iteration is great. Reduced time to market is great. Not writing a ton of documentation up front is great (maybe). But the consequence is that what you deliver is nearly always flawed and you accept that and iteratively fix it. I often wonder if that's really the right path for most businesses to take, at least for some subset of work.
I very much remember the days of writing BRDs and TRDs for months before a single line of code was written. It's certainly more fun nowadays, but the quality of what we deliver doesn't seem to match up, not initially and really not even after iterations because the sooner you start patching code is the sooner you start making it ugly code. And, when you sometimes have to do large refactorings because the architecture wasn't as well planned out as you'd like, that ugliness gets multiplied. You seem to always wind up with worse software, though at least you did it fast. There's this belief in "fail fast" as a viable strategy, and I'm definitely not convinced it's the right answer (again, for some subset of work - I don't think this necessarily applies to every project).
Maybe if it did have design specs, if we did have formal proofs for the things that logically can have formal proofs at all, and we backed away from Agile at least a little, we'd be in a better situation.
tcpukl · 1 points · Posted at 21:31:48 on April 27, 2018 · (Permalink)
I totally agree with everything you say, except may be it depends on which software we compare to critical systems.
I've never worked in 'business software', only 20 years in games software, after a Computer Science degree in the late 90s.
I think another big issue with being able to prove everything is the fact of inheriting old code. If you started from scratch, surely you could break down and prove everything. But if the code isn't written from the formal proof in the first place then your stuffed.
bsinky · 1 points · Posted at 12:55:34 on April 27, 2018 · (Permalink)
but it shouldn't the ONLY source of truth.
But I think it's the only guaruanteed source of truth. Documentation can become incorrect or outdated when code is updated and someone doesn't also update the documentation.
Definitely true, but I've always thought that comes down to treating documentation (whether in code or not) as being of equal importance and expecting the same sort of diligence and professionalism in maintaining it as we expect in maintaining the code itself.
For example, if you see a comment on a method that doesn't reflect what the code is doing because it's changed over time, isn't that really just a matter of diligence? A matter of responsibility? Fix the comment at the same time you fix the code and there shouldn't ever be out of date comments. Treat them with equal importance and it shouldn't ever be a problem.
pdp10 · 1 points · Posted at 22:36:08 on April 27, 2018 · (Permalink)
Fix the comment at the same time you fix the code and there shouldn't ever be out of date comments.
Yep, I started out my career writing lots of documentation, and I've actually regressed a bit on that because of how easily things get out of date. I'm all for good comments explaining why something is done a particular way, but not for comments that try to tell you what the code is doing. That's what the code is for!
In lieu of comments telling what the code is doing, I spend a little extra time refactoring until I have functions that tell you a story. If you want to know the details of a piece of the story, jump into a function. Most of the time you only will need the details to one spot.
The basic domain requirements and public standards seem a bridge too far for many programmers. Wikipedia is an amazing thing too. Pretty sure I've made a career out of reading documentation and asking stupid questions. My programming skills are just a by-product of giving up trying to explain things I've read after being told a question with an obvious answer has to be referred back to "the business".
So i'm an aspiring developer.. and i dont think i classify as exactly a novice either, I've been exposed to this stuff for 20 years and always had a pretty good mind for programming. But I find my biggest road block is not being scared to tackle the hard problems, but the constant voice in my head telling me there's probably a better and more obvious way to handle this problem, and I get even to embarassed to ask for help out of fear my code looks ridiculous. Any suggestions on this?
xerods · 27 points · Posted at 19:21:20 on April 26, 2018 · (Permalink)
It seems you have two choices. If you implement something that is suboptimal people will know when they see it. If you ask someone if they have a better idea then they will be proud of themselves for contributing.
I think this is why code/peer reviews are important. The job i'm currently at is very big on them and it has helped tremendously once I got over myself and stopped taking it personally. Every time someone goes over my code and points out the flaws or better ways to do it, it feels like I add another lego piece to my collection. Next time I do that, i'll have other, better options.
It's hard, but try to be humble and not afraid to ask for a second opinion. Most coders love to solve problems and help peopl solve problens.
If you find yourself doing it too often, draft an email detailing the problem and what you think will fix it along with other options. The act of writing it out often solves it (i.e.: rubber duck programming). Or maybe even go for a walk. I've had great solutions when not focused on the problem (too much depth, not enough breadth).
iktnl · 8 points · Posted at 21:22:25 on April 26, 2018 · (Permalink)
If you review your code enough, you'll
Get used to get honest feedback
Have some helping eyes to see where you went wrong
Learn from your mistakes
Learn how to explain your code efficiently if you think the reviewer got it wrong
You'll only hurt yourself and some poor sod in the future if you keep delivering "working" but unmaintainable hacks.
Feynt · 3 points · Posted at 20:09:23 on April 26, 2018 · (Permalink)
This is an easy one for me. The hard problems are usually hard because they're tightly coupled smaller systems. Don't look at an engine and say, "Man, that's way too complicated." Look at the spark plugs and pistons separately. Break down the fuel injector into more manageable parts. The same goes for programs. Sure it's a system that analyses billions of lines of text in seconds and outputs it in a completely different format as well as writes Excel spreadsheets and logs and stuff. But what's the pattern? It just takes things one to a dozen lines at a time, that's manageable. Figure out the parsing section separate of the export, Excel, and log sections. If you're just making your own stuff, think about the final goal and work backward, writing one little system at a time, and write the code to feed the output systems the data they need to do their jobs.
pdp10 · 1 points · Posted at 22:41:43 on April 27, 2018 · (Permalink)
Don't look at an engine and say, "Man, that's way too complicated."
Good analogy. When you know engines well, you can reason about them in the large and as a whole. When you're still learning them, thinking about isolated systems is vital.
Of course, engines follow certain design patterns, and these days don't differ tremendously within an application. An auto drivetrain engineer is still going to go back to basics if he's asked to work on a turboprop or a diesel-electric locomotive. Business systems can have more diversity.
Feynt · 2 points · Posted at 22:52:05 on April 27, 2018 · (Permalink)
Business systems can have more diversity.
Can and do are totally different things though, in my experience. Which is both exciting and depressing, and the reason I don't like enterprise programming. The exciting part is, "Hey! These crazy people actually do program like those guys in college!" So once you're there, you realise it isn't actually a field of high minded people casting a 1km shadow while you scrape through the bits trying to figure out what you're doing. The depressing part is, "Really? This buggy piece of crap that crashes on every day that ends in a Y is our production system? I just left a company that did this..."
pigvwu · 4 points · Posted at 20:34:21 on April 26, 2018 · (Permalink)
Exposure therapy. Show people your code often enough, and you'll get over it.
Also, try to accept that you will never write perfect code, but asking for help will make it better over time.
Create a design for your proposal, document the existing implementation and email that out to ask for feedback. This is what my group does when replacing existing code.
Your code probably does look ridiculous - and that's okay! Writing ridiculous code is the first step in learning to write elegant code. Don't be ashamed of mistakes - anyone who's done anything of note has made thousands.
Don't try to be perfect on the first try. Do it completely wrong, then go back and fix it. That's the best way to learn quickly IMO.
myrthe · 1 points · Posted at 22:58:45 on April 26, 2018 · (Permalink)
Write the first one as scaffolding. Write the first one as a rough draft. When asking say "this is my first approach but".
DON'T WRITE SLOPPY CODE. But write competent code that's good enough to solve the problem, and then look at refining it.
p1-o2 · 1 points · Posted at 08:51:45 on April 27, 2018 · (Permalink)
My advice is to get used to writing something wrong and then re-writing it. At work I might re-write the same part of a program 4 or 5 times before it's even ready to go into the master branch of code. You have to ultimately accept that you will get it wrong the first time and you'll fix it when you figure out why.
The hard part is recognizing when it's time to restart, and then motivating yourself to not throw your hands up while deleting your last 8 hours of work. Just gotta try your best. :)
pdp10 · 1 points · Posted at 22:37:58 on April 27, 2018 · (Permalink)
Being very familiar with the idioms of your language, being pretty familiar with the standard catalog of algorithms to solve problems, never doing something yourself when you should be relying on a standard library (like data and time handling), and code review.
I think so. It's a good read with a lot of practical advice. There are a fair amount of code examples, but always paired with quality philosophical explanations.
You just have to be self-aware enough to know that your optimism is actually a productive form of delusion sometimes.
"The fool didn't know it was impossible, so he did it" - Unknown
There's a certain naivety that is required for accomplishing large things. If I 100% accurately knew how much work a project would take at the beginning, I would never start most of them.
[deleted] · 1 points · Posted at 20:12:40 on April 26, 2018 · (Permalink)
Still, it doesn't matter how well defined your interfaces are or how separated the concerns or how elegant the snowflake. Software that is used, will be modified and the entropy of the code base will increase over time. Eventually the software will become brittle. The process can be slowed down, but it cannot be completely avoided.
Don't future proof your code. You don't need it and if you do, you can do it later. One way to have more maintainable code is to just write less.
nachof · 1 points · Posted at 23:50:17 on April 26, 2018 · (Permalink)
In a previous project we had refactoring Mondays. If you found something that needs work but wasn't part of your current task, you wrote it down on the project tracker, with a refactoring tag. On Monday first thing, before doing any other work, you took a refactoring task and did it. We started with what was probably the shittiest codebase I've inherited. We ended up with something that while it wasn't perfect, it was pretty good.
Their elegant might differ from what other developers on the team consider elegant, and
Now those developers need to learn Haskell to maintain this piece of code, a likely impossible task given the tech debt and fire fighting that comes with a 10M LoC codebase.
Rule 1 of software teams: accept the way your teammates do things. Redesigning during code reviews is death to progress and a certain way to kill morale. If it works and doesn't violate the requirements (including global requirements for style or maintainability), ship that fucker. Let them know there's a better way, but don't make them change to fit your idealism.
You've just been hired as an Engineering Manager at a company. You inherited a team that is maintaining a 15-year-old codebase with very, very few "modern" software development practices in place (they have Git and use it, but they don't really have any practices for merging back into master; they have Jenkins for CI, but it's really, really bare and is really only used to move code from their long-lived dev environment into QA and such). Releases are a huge pain, and introducing new concepts to said team is usually fraught with politics.
Tell politics to go fuck itself, keep the git, figure out how QA does its job but nothing gets merged back to the master branch, make sure the bug tracking system is operational, make sure verification is as driven as code, start jacking out releases (in whatever state they're in; that's what bug tracking is for) until it's second nature, and figure out where people like to drink on Fridays after work then go somewhere else myself.
make sure verification is as driven as code, start jacking out releases (in whatever state they're in; that's what bug tracking is for) until it's second nature, and figure out where people like to drink on Fridays after work then go somewhere else myself.
Okay, but now you're changing team dynamic, which isn't accepting the way that the team does things.
The point I'm trying to make is that sometimes you do have to change the team dynamic to make progress, and that transition can be painful. Unless you have a perfect team where all of the engineers are self-motivated go-getters that work nicely together and are always comfortable with change.
The way the team was doing things had problems, as mentioned in the problem statement. Nothing to do but lead them away from it.
You don't need to find the way everyone thinks is perfect (it probably doesn't exist if you didn't hire each of them into it). Just find a way they'll all accept that also solves the problems.
Well, start with making a list of "what hurts?". Why are releases a pain? Are different teams using different workflows for git? How are issues / bugs / feature requests tracked? Where are the bottlenecks and bumps going from the developer's local copy of the code to production? What do teams do differently from each other? Where does it make sense to standardize?
And I agree that politics can go screw itself. If you have team members who actively or passively resist improvements and concepts, they need to shape up or be let go. Those EGR (extra grace required) people will kill your team's morale and ruin many attempts at improving things. They suck all the energy out of the room and the other team members just stop caring.
Where I work:
Everyone leaves at 5pm and you are strongly discouraged from working on things after hours. Frankly, by 4pm everyone is likely mentally fried from bouncing ideas around, solving problems, and staying longer won't get anything useful done. We work a very strict 40 hours.
We lean into unit testing where it makes sense. And refactor code that is not easy to unit test to make it easier/trivial to test. We focus on testing behavior, not implementation details.
Pull requests must be reviewed by another developer prior to merge. There's no strict rule about who has to review it. We encourage the submitter to seek out someone knowledgeable for the review. This gives cross-pollination, second set of eyes, and other benefits. It also helps with the concept of "no code is sacred or beyond critique, especially your own". We've let people go (or they left) who could not handle code being reviewed.
Release cycles are two weeks long. It gives us a predictable cadence where week 1 is "make major changes, do the high-priority tasks" and week 2 is minor changes and stabilizing the release. Towards the end of week 2, major PRs are put on hold until post-release. Having a release cadence also makes the business happier because things are improving constantly instead of waiting 3-6 months for "the next big release". It also makes releases less risky because you are doing it 26 times per year instead of only 2-3 times per year.
CI/CD service tied into GitHub (or whatever) so unit/integration tests are run on all PRs prior to merge. And the development site automatically gets deployed whenever someone merges to the development branch. Production/QA site deployments work the same way. No need to remember arcane commands to deploy.
We start our release notes as soon as we have the first PR merged into development. We use it to track things that have to be done pre/post deployment into the various environments. The sooner we jot down that one-line reminder, the less likely we'll forget about it on the day of deployment. Release notes also give visibility into what's coming and how big the release is getting.
We use a kanban board with pipelines for keeping track of which issues on the milestone are up for grabs (developers have some freedom), being worked on, ready for testing.
How one approaches people can greatly dictate their level of resistance. It is a hard problem, though. The hypothetical engineering manager should have support from the rest of the business, and it would be really nice if some organizations piloted hiring social psychologists or counselors to assist with these kinds of problems instead of trying to achieve good teams using only the hire/fire approach.
and it would be really nice if some organizations piloted hiring social psychologists or counselors to assist with these kinds of problems instead of trying to achieve good teams using only the hire/fire approach.
That would be amazing. Firing people is really hard, almost to the point of psychologically trauma. (Imagine telling someone that's been a solid contributor and is providing for their family that they are no longer required. You just fucked up their life, even for a short bit. While we all should be prepared to deal with that, especially here in the US where most employers hire at-will, it is still traumatic to do that to someone you'd rather not do that to.)
Yeah, no one wants to have to do that. But there would be some difficulties: strict confidentiality would be required in some cases. That might be hard for companies to swallow. It would need to be different from HR, where liability to the company is the primary concern and most people know well enough now to not overly confide. Coaxing out resentments and such would require some guarantee of safety.
pdp10 · 1 points · Posted at 22:51:22 on April 27, 2018 · (Permalink)
it would be really nice if some organizations piloted hiring social psychologists or counselors to assist with these kinds of problems
There's room for mentoring to be a solution here, if the decision-makers are interested in getting to the root causes of the problem, and the team has the bandwidth.
TEKC0R · 79 points · Posted at 19:56:58 on April 26, 2018 · (Permalink)
Amazing how relevant this is to me right now. I used to work for a dev tools company. They have a massive framework collecting code over the last 20 years. And a userbase of developers who rely on that framework.
About 5 years ago it was decided to deprecate the entire framework and start over. Most of the engineers were on board with this idea, but I never was. In public, I would basically stay silent, but in private they knew damn well that I thought this was a terrible idea.
It lead to turmoil between me and the rest of the team. Enough that 3 of them were able to fabricate some bullshit and get me fired.
The new framework was introduced. And it was missing a TON. No RegEx, no basics like hex or base64 encoding... it was a wreck. Customers never really got on board.
Yesterday the company announced they were giving up on that plan and doing exactly what I originally suggested: fix the damn problems.
For example, FolderItem.Item uses a 1-based parameter instead of 0-based like everything else. This is confusing and needs to be fixed. So don't throw away the entire class! Deprecate .Item and introduce .Child with a 0-based parameter. This is simple stuff, there was no reason to throw everything away.
I feel vindicated. But at the end of the day, that was my favorite job and I lost it. So this also just fuels the my rage.
Wow this is some big kind of bullcrap. I will still be so mad if I was you.
TEKC0R · 5 points · Posted at 10:51:37 on April 27, 2018 · (Permalink)
I’m a very laid back and level-headed person. The people around me would tell you it’s very rare to see me genuinely mad. I try to let things go.
I’m not sure I’ll ever get over this though.
I’ve thought about revenge. I have ways I could hurt the company so bad. But that’s not who am I and my beef isn’t with the company so much as it is with those 3. I don’t want to hurt the company. I still want to see it succeed, even if I can’t be part of it.
Is it at all possible for you to get back in? Depending on the kind of bullshit that was fabricated, this might not be unreasonable. (e.g. "well, I know I was let go for allegedly stealing envelopes from the mailroom, but that was a long time ago and I've dealt with that problem. I still believe in the company, the product, and the people here, and I think I've got a lot to contribute.")
TEKC0R · 3 points · Posted at 16:04:49 on April 28, 2018 · (Permalink)
I honestly don’t know. On one hand, I’m still on good terms with the boss. I’ve been helping him pick parts to build his son a gaming PC. He was pretty much forced to let me go because those 3 said “either he goes, or we go.” In a small team, he couldn’t afford to lose all three.
On the other hand, I’m now making twice what I was before, so I’d be expensive. And I have no idea if the other guys could suck it up. Or if I could remain humble.
Maybe but if you have a working product why do rewrite the whole thing? In the end it will end up introducing new bugs either way. Just take what you have and fix it.
What is it with throwing away old things instead of fixing what you have?
New bugs are preferable to a code base that doesn't actually fit your requirements. There's a good chance that new processes and language improvements will reduce your bug rate. The caveat is that you have to retrain or replace your staff to have the skills to make it work.
So you will re do a project everytime? Is that even cost effective? If you are going to retrain your staff why not 'retrain' them in following programming techniques that actually may help in keeping a project maintainable like functional programming?
Depending on the context. You maintain existing applications for new releases on the same hardware, but occasionally redo it from the ground up because your old mistakes start to propagate inefficiencies throughout the rest of the code. Anything with significant hardware changes and full-boat verification involved, you're probably better off just starting from scratch, unless you designed it from the beginning to work on two platforms. If you did a really good job on generic utility code you'll probably keep that, but it's a small fraction of any big project.
"Legacy code" often differs from its suggested alternative by actually working and scaling.
Bjarne Stroustrup
[deleted] · 12 points · Posted at 19:12:40 on April 26, 2018 · (Permalink)
Isn't it more that over time the problem shifts slowly so that eventually the original breakdown is no longer relevant? For some period in between, hacks and workarounds are used to solve the new problems with the old framework, until eventually it becomes so time consuming that it makes sense to re-write the whole thing based up updated assumptions. Then the process ineveitbly starts again.
Not really. A class library is just that and its purpose is to provide types and methods/functions/subroutines/whatever you want to call it for the application to explicitly call. What you probably meant to refer to are IIFEs, and modules do have them for initialization of constructors and such, the scope is seldom above that for obvious reasons. Then of course there's monkeypatching as was mentioned.
My point is simply that I can import in Python and have code executed.
Doesn't matter how you define a class library, it's something that can be done very easily. So "import solution" could very well be a valid program if so desired. Just like "import antigravity" from the system libraries executes an action.
It is indeed not how most libraries are implemented(or should imo), it is however an option and the previous commenter was not wrong.
flukus · 3 points · Posted at 22:36:23 on April 26, 2018 · (Permalink)
I'm working on a product now who's sole purpose is to import CSVs in various formats. It features a plugin system with dynamic loading, our own special regex language and all sorts of overengineering. To add a column to one plugin took me a week and I had to touch 12 files held in a delicate balance.
10s of thousands of lines of code and I'm pretty sure it could be replaced with a dozen short bash/perl/awk scripts.
[deleted] · 3 points · Posted at 03:07:36 on April 27, 2018 · (Permalink)
[deleted]
flukus · 2 points · Posted at 04:49:07 on April 27, 2018 · (Permalink)
It basically translates the csv files into SQL insert statements, there's very little validation to do and the supervisor process doesn't do much.
It's a simple problem that was made complex by Devs trying to solve a more interesting meta problem.
pdp10 · 3 points · Posted at 22:59:25 on April 27, 2018 · (Permalink)
Write some tests and then write a new implementation against the tests.
CSVs are kind of a worse-case record format, though, for historical reasons and because of data and i18n concerns revolving around the record separator ','. TSV is much simpler, more elegant, and less likely to go wrong. But ASCII itself has group, record, and unit separators since the mid 1960s, because record-based files used to form the backbone of data processing with computers.
I've worked with ETL systems and the records are never the unexpected or interesting part.
As a non-programmer, I understood all of this. You must be quite competent in your field that you are able to put it so elegantly in layman term, and I appreciate you for taking the time to do so.
Yup. And that doesn't even cover that once a code base gets large and complex enough implementing it identically again becomes close to impossible and by then other big complex systems that interact with it that are designed to deal with how it works right now (bugs and all). So now you have at least one, usually more, additional code bases that needs to be changed and then another that uses that second system and keep repeating (often looping back round to the first system) and getting everything working properly becomes impossible.
[deleted] · 1 points · Posted at 20:05:43 on April 26, 2018 · (Permalink)
There are only two reasons to rewrite code:
legacy software that leads to old inefficient technology or incompatibility with new software (not legacy code)
performance optimization
If you can't read existing code, then you need to go back to school or get more training and experience from reading more open source code bases.
rdtsc · 1 points · Posted at 06:55:54 on April 27, 2018 · (Permalink)
If you can't read existing code
I disagree. It's easy to write code that is hard to understand for someone else (or yourself later on). Bonus points if people try to be "smart" and play compiler, optimizing things manually because they think it's faster. But the only thing they are doing is obscuring the meaning.
I once abstracted the data access layer in a project of mine.
which used Entity Framework.
so i made the POCO classes seperately for each implementation as well.
not the best ideas
role34 · 1 points · Posted at 19:52:27 on April 26, 2018 · (Permalink)
damn, i always thought this was wrong or felt wrong. I have this fear that if i don't know something in a problem or assignment, I'm not learning or progressing.
On the other hand, if you don't throw it out eventually, you'll end up having to hire programmers that know obscure legacy languages at double the normal salary.
I would fully agree with this. With some of my projects, they will be thrown out because of how they were designed at the time. Low time, plus high push to finish on time led to something that does exactly what you want it to do, but does not look good and definitely has room for optimization.
That isn't wrong. The truth is, 90% of "reuse" is misguided. Start with new requirements and write new code using new methodologies. The way the people who are getting rich are doing.
Either that or the code is complete garbage, the UX interface is trash, and all the feedback is horrendous...
[deleted] · 1 points · Posted at 01:28:49 on April 27, 2018 · (Permalink)
So what you’re saying is that Bluehole can’t scrap PUBG because it’s making so much money despite its shitty performance, and recoding it is the proper way of handling it. Gotcha.
I am currently the custodian and maintainer of approx 500K lines of C++. I began working on this particular project in 2007 with a senior team. They have all since retired or moved on. Fortunately, the code is highly modular and very well organized. But I am "the dude" now, and I feel like I only have a deep intimate understand of about 40% of this software. But because it is well organized, when bugs are found (and they are still found), I can usually trace the problem down in an hour or two.
Which is why simpler more readable code is often better than clever elegant code. If someone later has harder time figuring it out it isn't worth it. Maintainability is usually more important than performance.
There's another half of the problem as code ages. There's a case where every step of evolution in the code made sense given the previous state and the goal of the developer at that time, but collectively they are no longer the most direct way to represent the total system. There's also sometimes the results of incomplete refactoring and other ways for hard to understand code to creep in.
The big reason that I think rewrites lead to better code, though, has nothing to do with any of that. It's that if you're forced to rewrite code, you end up throwing away some features that no longer have value to the system. I have a theory that a huge chunk of the "it would be so much cleaner if we rewrite it in a different language" turns out to be true is just the fact that changing languages means you lose some ability to just copy the code you don't understand into the new place (or call the existing libraries, etc). If you want the functionality, you need to understand it and implement it. That also means your reviewers are likely reviewing it in one change and not a series of 2-3 line edits spread over 30 people and 5 years.
Heh, at the project I'm at now it's not even the whole solution that can't fit person's memory. Just a single functionality in the code is so convoluted it hurts and to this day I haven't seen use cases for it documented anywhere, so only few people REALLY now what it's supposed to do but they keep that knowledge to themselves..
The spaghetti pattern resulting of years of maintenance and looking at the initial commits even initial creation was in some places shit.
There are ways to avoid 25 parameters in a single method ffs. Or classes that span over 1k lines and do a lot of things not related to their domain. Or methods with 200-300 lines and complexity of 20+.
snerp · 1 points · Posted at 16:27:22 on April 27, 2018 · (Permalink)
There are situations where the legacy codebase is completely unsalvagable
I've seen some amazingly bad systems, but even then I was able to salvage 'something' out of the old system. Stored Procedures, some business logic, maybe some html or images. Even if it's a dumpster fire, you can still use the dumpster.
DrunkMc · 512 points · Posted at 14:30:54 on April 26, 2018 · (Permalink)
I think most code, no matter how well designed before hand, is designed mostly on the fly. You always run into things you didn't think of and adapt. This leads to cludges and breaking the design. Once everything is done and it works, I love nothing better than tearing it all down and re-writing it with all lessons learned.
I find this to be the case when I teach students. For homework problems which may be encapsulated within only 100-200 lines, I actively advocate for saving a copy of their non-working code once they figure out what they need to do, and re-writing from scratch using their old code as reference and their knowledge gained.
I think computer science/programming students have too much of a habit of hanging on to their old code because of the sunk-cost, but in reality it's easy to overlook some small bug in your code if you're only reading and not re-writing.
I would say that for even large code bases, as long as the constitutient parts are abstracted out, re-writing a large section isn't bad. That's the whole point of abstraction anyway. It's just getting to that point where you can easily rewrite disjoint sections of code is hard.
rush22 · 21 points · Posted at 22:43:26 on April 26, 2018 · (Permalink)
Yes it's a great way to learn, but bad for business.
Tasgall · 28 points · Posted at 03:16:03 on April 27, 2018 · (Permalink)
It depends, sunk cost fallacy is bad in business as well.
That is a good method. The next step is pseudo code/PDL - read "code complete" by Steve McConnell - the section on PDL.
That said - the thing that changed how I code the most is doing the exercises at the back of "A Discipline for Software Engineering" by Watts S. Humphrey
I would say these 2 have changed how I code more than any other book.
NAN001 · 27 points · Posted at 20:38:39 on April 26, 2018 · (Permalink)
I do exactly the contrary. When given a big spec, I usually feel overwhelmed on how to architecture the solution because there are so many things to think about, so I simplify the problem, temporarily ignoring some requirements or even features. When I say "ignoring", I mean literally. I start designing, then programming, a first iteration of the thing, totally incomplete, pretending it's the end product. Once I know this iteration is done and solid, I add more stuff from the spec. I study how the existing code must be refactored and changed to host the new requirements (which weren't actually new), which often involves a bit of code rework, and this way I build the next iteration. And so on.
Depending on the context (deadlines, co-workers, priorities, etc), I can apply this process more or less properly, and I know that when I apply it properly I produce the best of code. The main difference I find between this technique and the "agile" process where new requirements appear out of nowhere (which I could theoretically integrate gracefully into the existing iteration following my technique), is that a finished spec has some sort of consistency whereas many actual new requirements makes no sense and come with a weird sort of inherent complexity as if it was fundamentally incompatible with the original requirements.
pdp10 · 1 points · Posted at 23:02:54 on April 27, 2018 · (Permalink)
a finished spec has some sort of consistency whereas many actual new requirements makes no sense and come with a weird sort of inherent complexity as if it was fundamentally incompatible with the original requirements.
In most agile methodologies, it's not required for the team to accept the item. Either don't accept it into the backlog, or give it the scarlet letter of "Epic" until you can devise a strategy for it.
hugokhf · 45 points · Posted at 19:38:39 on April 26, 2018 · (Permalink)
Once everything is done and it works, I love nothing better than tearing it all down and re-writing it with all lessons learned.
Once everything is done and works, I just like to leave it alone. Are u the werid one or am I the weird one?
Oncra · 24 points · Posted at 19:59:49 on April 26, 2018 · (Permalink)
I think the best practice is to constantly review and refactor existing code (assuming you have the manpower to do so). That can be hard with management that doesn't understand the process or with programmers who want to always work on the latest and greatest.
The long-term benefits and business value of moving from "good code" to "great code" with a little bit of love is immeasurable.
Really depends on your test coverage. I know a lot of places where you’d have a hard time explaining to management why you “fixed something that isn’t broken” and then broke it. Maybe financial software is just a different beast altogether and other realms are less intense
I'm a strong proponent that refactoring requires good automated test coverage. And as much as possible, that should be tests that can be run locally by the developer, in under 10 minutes (preferably 5 minutes). If the IDE can run them automatically as code changes? Even better.
In the real world, that's not always possible with legacy code. So you may need to start by doing a minimal refactor of the code to make it more testable (dependency injection, etc.). Or make other changes to the system to enable faster tests.
m50d · 1 points · Posted at 09:38:49 on April 27, 2018 · (Permalink)
Finance has its own weird conventions because everything is so tied to trading hours, so your code actually doesn't need to be that resilient over the long term (you can have 2 hours' downtime every weekend and no-one cares - the people who work on e.g. AWS would kill for that) but it's absolutely vital that nothing goes wrong during market hours on a weekday.
I just like to leave it alone. Are u the werid one or am I the weird one?
You're not weird, you're just not considering the future additions to the project that will be massive undertakings in the old kludgy system but could be easily done in a system developed in hindsight.
I'm just coding in python for fun, but I'm never done with my projects. There's always something to change. And there's always a ton to do. From fixing all the bad solutions from when I did know better ways, to structuring, renaming, and documentating. Not to mention a new feature, or better coving for edge cases or other unlikely but possible situations.
I am learning as I go along, and some things are just so massive it'll take ages to learn, but you can get solutions that work, but later find much better ways to do things.
And this is where people go wrong. If you discover, once you start implementation, that your model doesn't fit, stop! Think about how you need to change your model to accommodate this new data. Refactor/rework now, before you commit to a path that you now know doesn't work. Doubling down on a bad path is, long term, considerably worse than investing in the right plan early. At least in my experience.
Oh, I love that. I've experienced it directly. Bug tickets filed because requirements changed but were not communicated. That's not a bug, that's a project manager failure.
PRs? What's a PR? I don't think subversion has a "PR"... Anyway, someone else on the team just pushed code into QA, and no-one will fess up to it. We're having a meeting to discuss this in 10 minutes, because it's Friday tomorrow and we have to demo our failures to steakholders.
Well, then, we're going to have to discuss how this changes the deliverables for Friday. The scope of the project is different than was anticipated.
Also, if you're iterating and measuring, by the time actual delivery comes around, this should be worked out already.
And my final point is that eventually, we have to be willing to say we're not going to ship unless a certain quality bar is reached. Sure there are compromises, but in my opinion, many developers are way too willing to sacrifice code quality to meet unrealistic management demands. That's a fool's trade.
I work for one of the largest CDNs in the world. We HAVE to keep it running, and it has to have 100% uptime. This is the facts of our business.
What happens as we grow is that we are constantly hitting new bottlenecks. Things that worked fine with 30 thousand servers suddenly stops working at 35 thousand. Nothing scales perfectly horizontally.
So, we now are up against the clock. We know our system is teetering towards falling over, and we can keep it up for the near term with a lot of massaging and duct tape, but we need to write some new code to fix the bottleneck.
We can’t just say, “we aren’t going to ship yet unless we meet a certain quality.” Not shipping is not an option, because not shipping means hundreds of millions of dollars lost and 1000 people out of a job.
Obviously, we try to avoid these situations whenever we can, and most of the time we are planning out work in advance and spending the proper time to build with quality, but the unexpected still happens.
Don’t tell me I am a fool for sacrificing quality when the alternative is the collapse of our entire company.
Yeah, I can totally understand and agree with OP's ideals, but that's just not how the real world works. Experience will teach developers how to make the decision on whether those extra 4 weeks of developer time to make sure a solution is "correct" are justifiable for the business in both the short and long term
I'm sorry that you felt personally insulted by my statement.
I agree that my positions are rather idealistic. It's just been my experience that sacrificing quality has a much longer-term cost than people realize, no matter what scale you operate at. And I strongly believe that being putting in the situation of having to make that choice is a sign of failure elsewhere. It seems clear to me that if one ends up at the point of having to make that last minute choice, well, the horse has already left the barn. You're already in a reactive-only mode.
And, please don't take this the wrong way, but if the choice is shipping this change or the entire company collapses? Well, that seems rather hyperbolic. And if it's not hyperbole, then I would be seriously concerned about the viability of the company.
I am sorry for the tone of my reply, I wasn't trying to come off as personally insulted. My last line was certainly over dramatic.
I also realize I might have made it seem like our company was constantly behind the eight ball, always completing things at the last minute just well enough to get by. That isn't the case at all; most of the time, we have plenty of time to plan and execute with quality and attention to detail.
The point I was trying to make was that that isn't always possible. If you work for a successful company, you get to a point where taking down time is simply not an option. And sometimes, unexpected things happen that cause issues that must be fixed with new code very quickly, and you sometimes have to take shortcuts to complete the work before things become so bad that you can't keep production up.
Now, of course, once you have the new code out, you absolutely should take the time to try to go back and improve that code, and make it more robust and easier to maintain. You can't, however, just choose not to push it to production until it is up to your highest standards.
As for it being hyperbole, it is in the sense that it isn't a super common occurrence; it isn't like we are facing this existential crisis every week. However, it is not hyperbole to say there has been times where not solving the problem quickly enough would absolutely put the survival of the company in danger. In many ways, a CDN is a commodity business; if we don't deliver absolute reliability, our customers would switch to a competitor in a heartbeat.
[deleted] · 3 points · Posted at 02:02:09 on April 27, 2018 · (Permalink)
I realize there are real consequences. I don't mean to suggest there aren't. But at the same time, management, product and various other stakeholders have to, at some point, be held accountable for unrealistic demands, promises made to customers without engineering buy-in and all the other ways they put engineering into these extreme positions of ship or sink, quality be damned.
Edit to add: next sprint? You should see the list of features we have lined up for that! We'll have to address that debt later....
If you discover, once you start implementation, that your model doesn't fit, stop
This is very wrong.
Your first priority is to make something work, if you are tying yourself up on architecture before you even have a working prototype you're wasting everyone's time. You will run into yet another part of it that doens't fit the architecture you thought so hard about, and you're back to fussing over it again.
When you have something working, you know about all the moving parts, you know what goes where. Now that you know this, you can refactor it to be elegant and performant with relative ease.
Well, I didn't say anything about whether the thing was working or not. In my experience, you can't know whether your model fits or not until you've got at least a mostly working prototype. Nothing about recognizing that your model is incorrect prevents that. I agree, it sure looks like that's what I'm saying, so I apologize for not being more clear.
The problem, as I see it, is that everyone has a different idea of "Make it Work". For me, that's the minimal amount of code needed to exercise the most simple happy path of operation. (almost) No design survives that process. Where people go wrong is that they take that design and commit to it even though it's clearly not working. And then the kludges pile up and you're hosed.
But I should clarify that nearly all of my professional experience has been coming into startups that are trying to transition into not being a drunk teenager (the best way I know to describe startups). So that colors my views heavily. It's nothing but doubling down on bad design decisions, repeatedly, for years.
But I should clarify that nearly all of my professional experience has been coming into startups that are trying to transition into not being a drunk teenager (the best way I know to describe startups). So that colors my views heavily. It's nothing but doubling down on bad design decisions, repeatedly, for years.
This accurately describes 1/2 of developers I know.They will follow very bad practices, and when you point it out, and the results of it. Instead of learning and looking into why they might want to change, they double down.
It is not black and white, not all technological debts are the same. I agree is more important to make it work, but you need at least to make sure an affordable refactory will be possible to reach the next points.
Keep in mind that, I at least, can easily get lost in this. No, your data structure will never have more than 10'ish elements (i.e: provinces in Canada). I shouldn't spend any cycles on making it faster.
I feel like coding can be a lot like writing in general. When academics write papers or journalists write stories a significant amount of time goes into editing the writing. Papers and stories can be edited double digit numbers of times. I don't do this when im coding most of the time. Usually I code so that it functions properly, I don't go back and edit it like I would a paper. I try to make my code understandable when im writing but once I have a function name I usually don't change it for instance. So the code will get the point across, but its a first draft essentially.
[deleted] · 5 points · Posted at 20:47:24 on April 26, 2018 · (Permalink)
Usually even if you do get to do a rewrite, you run into Version 2 problem.
Every idea and the kitchen sink gets thrown into Version 2, and it ends up over-engineered overcomplicated mess that is slower, larger and even harder to work with than Version 1.
I worked in the defense sector. You literally spent years on design and documentation and review before you did anything more than a test stub or proof of concept.
Yeroc · 2 points · Posted at 03:03:55 on April 27, 2018 · (Permalink)
Yup, the first working program should be considered a draft the same way an author considers their first written version of a book a draft. Unfortunately, many developers stop at the first draft and consider it done leaving a mess. We're reading Clean Code by Bob Martin and this is an insightful comment he makes in his book.
This is doing it right though isn't? In most cases, if you've learned nothing from the system you built on how you can build it better if you had a second go round... then you learn nothing?
Here I have this module that had the first line of code written 6 years ago when I wasn't even part of the team. Since then, it went to 3 major redesigns, but we never tear it down. Because it was doing what it was supposed to be doing, and it was doing it the right way. It has a lot of bug fixes, edge cases discovered by mistake, cases that may happen once/year for a customer. I'm now one if its main maintainers. I recently refactored it again in order to simplify some things (mostly code cleanup).
If it would just disappear overnight and I'd gather together the developers who researched, created and fixed it along the time we will not be able to make it better. It might look better to us after we're done, we will probably avoid some design decisions that had to be fixed after its creation, but we will surely bring back old bugs and introduce new ones.
I have more trust in old code paths than in new ones.
The old mantra build one to throw away is dangerous when applied to large scale commercial applications.
It's not a mantra without reason. I already have the quotes written up from The Mythical Man Month:
“Programming system builders have also been exposed to this lesson, but it seems to have not yet been learned. Project after project designs a set of algorithms and then plunges into construction of customer-deliverable software on a schedule that demands delivery of the first thing built.”
“In most projects, the first system built is barely usable. It may be too slow, too big, awkward to use, or all three.”
“The discard and redesign may be done in one lump, or it may be done piece-by-piece. But all large-system experience shows that it will be done.”
“The management question, therefore, is not whether to build a pilot system and throw it away. You will do that. The only question is whether to plan in advance to build a throwaway, or to promise to deliver the throwaway to customers.”
“Hence plan to throw one away; you will, anyhow.”
The whole point is that the first time you make any system, you don't know what you're doing. Every decision has a non-zero element of speculation. Some of those decisions will be fundamental. Insights from making the first system mean you can make the better decision without speculation the second time. If you try to keep the old system forever and just patch it repeatedly, that becomes an uphill climb: the longer you maintain a difficult-to-maintain system, the harder it becomes to maintain. You'll eventually reach your goal but you won't have planned for all the extra work. Even as the authors of a system.
The idea that new code is better than old is patently absurd. Old code has been used. It has been tested. Lots of bugs have been found, and they’ve been fixed. There’s nothing wrong with it.
Yeah, that's the problem with crappy code. You think that there's nothing wrong with it because it's been tested. But how do you know? Nobody apparently understands the code. Often, code is so bad that nobody knows how buggy it is. Look at OpenSSL, for a public example.
The code that programmers hate to maintain is when it's like walking into a haunted house and ghosts follow you around whispering seeds of doubt every time you open a cupboard or walk past a mirror. They'd prefer to set fire to it and put the fire out with holy water.
People like clean, simple code because it's obvious that it doesn't have problems.
I absolutely, sincerely agree with everything you said about writing software.
However, I think there's one thing that may be commonly misunderstood about Joel's original article:
Well, yes. They did. They did it by making the single worst strategic mistake that any software company can make: They decided to rewrite the code from scratch.
I've always believed that Joel's article was written in the context of a software company choosing to rewrite its core product from scratch, and this article was written in back in 2000 when "being a software company" pretty much meant "you ship regular versions of your code, and sell them to customers, and if you miss/botch a release maybe your company will die, especially if that product is your only product."
Within that context, yeah, rewriting code from scratch is a very, very dangerous thing to do.
I don't think Joel is advising that no code ever be rewritten, or even that no large project should ever be rewritten.
Or maybe I'm wrong! Maybe I'm giving him too much credit.
I still like many things about this article, even if the central premise is kind of a blanket statement that isn't always true, and is also kind of a strawman argument because most people don't mean "literally throw away all the old code and never look at it again" when they say "rewrite."
I like this part:
Back to that two page function. Yes, I know, it’s just a simple function
to display a window, but it has grown little hairs and stuff on it and
nobody knows why. Well, I’ll tell you why: those are bug fixes. One of
them fixes that bug that Nancy had when she tried to install the thing
on a computer that didn’t have Internet Explorer. Another one fixes
that bug that occurs in low memory conditions. Another one fixes that
bug that occurred when the file is on a floppy disk and the user yanks
out the disk in the middle. That LoadLibrary call is ugly but it makes the
code work on old versions of Windows 95.
Each of these bugs took weeks of real-world usage before they were found.
The programmer might have spent a couple of days reproducing the bug in
the lab and fixing it. If it’s like a lot of bugs, the fix might be one line of
code, or it might even be a couple of characters, but a lot of work and time
went into those two characters.
In my experience, this is true. The "old code" generally has a lot of these little hacks and kludges to fix real-world problems. No matter how beautifully an application is (re-)architected, there are always going to be bizarre little things that just have to be dealt with, even if they junk the code up a bit.
In my experience, this is true. The "old code" generally has a lot of these little hacks and kludges to fix real-world problems. No > matter how beautifully an application is (re-)architected, there are always going to be bizarre little things that just have to be dealt with, even if they junk the code up a bit.
"look at this thing, all these corners! Customer didn't order a d20! Let's scrap this and start all over with a nice round, simple ball."
m50d · 2 points · Posted at 09:44:18 on April 27, 2018 · (Permalink)
Not always. Sometimes when you look at the problem the right way, all the corner cases become ordinary cases. And generally that's what shows you've really understood the problem, because the business users normally don't think of their requirements as corner cases - they think "obviously you do one of those that way".
Occasionally you do meet genuine corner cases, but my rule is that the only legitimate reason for it to be a corner case in the code if it's also a corner case in the domain - the code should be as complex as the problem it solves, but no more complex.
phySi0 · 0 points · Posted at 13:13:24 on May 10, 2018 · (Permalink)
This is not the case. Code can be rewritten so that former corner cases no longer are. I can't be bothered to think of / find a screencast for a complex example right now, but a simple example of a pattern that destroys a corner case is the null object.
Not all corner cases are inherent to the domain, and approaching the problem with a new perspective may well remove certain corner cases.
guepier · 47 points · Posted at 19:09:53 on April 26, 2018 · (Permalink)
IIRC Joel has subsequently stated explicitly that he disagrees with Mythical Man Month about this. Or, rather, he said, in his modest way of speaking, “MMM is wrong here.”
Let's not give Joel altogether too much credit. He's smart, and he's influential for a reason, but many of the things he's blogged about lack nuance, are dogmatic, or go against what the evidence shows. And his business decisions are also quite hit and miss. The original FogBugz was written in his own VBA derivative, after all. And was subsequently rewritten from scratch in a sane language, ignoring his own written advice. So there’s that.
In his defence, even those articles where he was (in my view) wrong usually contain an interesting perspective and some good arguments.
bhat · 38 points · Posted at 22:13:06 on April 26, 2018 · (Permalink)
Sometimes the well-articulated arguments of a highly-opinionated person are valuable because they start a useful conversation, not necessarily because they're correct.
Xaxxon · 3 points · Posted at 23:20:02 on April 26, 2018 · (Permalink)
Rules are rules for people until you realize why they are rules. At that point you can understand them it’s appropriate to break them.
I don't think Joel is advising that no code ever be rewritten, or even that no large project should ever be rewritten.
Or maybe I'm wrong! Maybe I'm giving him too much credit.
My own takeaway from the article, and I first read it when I was struggling to convince my team to avoid a rewrite, is that rewrites are often a fallacy. They're very tempting, for a couple reasons. For one, it's easy to make quick progress on a clean sheet project, and harder on a more mature project, so it's tempting if you're looking to make quick progress, but, naturally, the rewrite will slow down again as it gets more mature.
For another, and this is pretty much the title: more novice programmers haven't yet honed the skills to differentiate bad code from code that's hard to read. And that's not an easy skill. So they make a common mistake, which is to think that problems with the codebase stem from the code being bad, so they'll rewrite it with GoodCode(TM) and it'll be much better. Frankly, it's a pretty arrogant attitude.
Sometimes bad code really is bad code, and then you should rewrite that code. Sometimes bad code is just hard to read, and you should add comments or refactor it to make it clearer. But ultimately, try to have confidence that you're using the right tool for the job. Refactoring bad code is pointless if it's somehow flawed, rewriting hard to read code will just introduce new bugs.
I ultimately failed to convince my team to refactor instead of rewrite, and they spent about 2 years rewriting code that I estimated would have taken a few weeks to refactor. The leader of that team got fired.
The siren call of whole rewrites is so alluring because we see how elegant the first 90% of the solution is, but not the second 90% that introduces all of the ugly. Then it's time to rinse and repeat.
zeuljii · 80 points · Posted at 18:23:50 on April 26, 2018 · (Permalink)
Those hacks and kludges need to be documented, associated with their cause, and forwarded to the manufacturer of the issue. When the issue is addressed they need to be revisited, or if not followed up on.
If you aren't tracking that... if your house was held together by string and tape, and you didn't know why, what would you do?
If I know the problem, I look for a better solution. If I don't, I rebuild.
Good luck if it's a quirk of some major software company's product that is like that to be backward compatible or can't be changed for whatever reason. Sometimes you simply can't fix what's broken and have to tape over it.
I lost count of the number of code comments I wrote that detailed exactly why the obvious, clean solution can't be used.
Yep, some manufacturers will never fix things. Some aren't even around, but for those who are, it's better they know. When you're a manufacturer it helps with priorities and awareness. As a consumer you can encourage them to break backwards compatibility.
In any case, you track it. You know who is fixing their issues, and you can respond when they do (or consider ditching them if they don't).
And sometimes you can't, for business reasons, get rid of a bad manufacturer. But at least you saved the next guy some time.
amunak · 8 points · Posted at 20:04:40 on April 26, 2018 · (Permalink)
Good luck if it's a quirk of some major software company's product that is like that to be backward compatible or can't be changed for whatever reason. Sometimes you simply can't fix what's broken and have to tape over it.
You're right, but the point is to document those little things even when it might seem meaningless or obvious. Because when you later decide to update, rewrite or whatever, and this time maybe without supporting that old platform that you wrote the quirk for, you can simply remove the fix and cleanup the code even if the bug hasn't been fixed at the source. You simply no longer support it.
But when it isn't commented, eventually you end up with a huge, smelly heap of "tweaks" and "corner case fixes" but noone knows what each of them does, why, how they react to the rest of the code... And you end up having to rewrite it all from scratch instead of just having to remove most of the bad code.
Personally I find this is the only legitimate case where comments are needed in your code. The "what" should be obvious, the "why" should be explained. Like "why" you need to check the JSON you're supposed to get back from this service isn't actually just a plaintext string that will choke the parser.
Comments are the meta-code to help you or the person after you understand the code at a higher level than simply "what does it do?", if you're not adding them then you're making it more difficult to maintain.
I've been doing this for 20 years and people look at me like my hair's on fire when I insist that those sorts of kludges be documented.
edit:
The reality is:
A lot of coders straight-up don't believe in commenting code, and actively argue against it. (Let alone doing any of the other helpful things you suggested) They fervently believe comments are a code smell, because all methods should be short enough and descriptively enough named that their intention is blindingly obvious. And even when that's not the case, and a comment would be useful, they stick to their "comments are bad" mantra.
A lot of conscientious coders do their best to comment bizarre hacks and kludges. However, while they tend to document the really bizarre stuff... they often don't realize how bizarre certain things look because they're too deep in the code to realize it.
Unless you have been working in this industry under a very peculiar set of circumstances, you will spend time working with other peoples' code and it will have inexplicable things in the code.
edit 2:
In case it's not clear, I absolutely agree with you. A lot of the uncertainty associated with a rewrite could be avoided if people simply documented all those little hacks and kludges, so that future coders could make reasoned decisions about what's necessary logic and what's merely dead code.
you will spend time working with other peoples' code and it will have inexplicable things in the code.
Yep. I literally removed an empty while loop and broke one of our programs. Shit gets weird sometimes. That loop should definitely have had (and now it does have) a comment saying "DO NOT REMOVE; HAS ODD PROGRAM-SAVING SIDE EFFECT."
kenpus · 5 points · Posted at 14:34:11 on April 27, 2018 · (Permalink)
The comment should really go into a little bit more detail, but it's positively much better than no comment at all.
Me: "Hey team, since all major browsers have a considerable amount of support for ES6 I'd appreciate it if you could switch from using indexOf() to check for inclusion to includes()"
Dev: "Well what if they don't have ES6 support?"
Me: "Thats fine, we've been using a polyfill for years anyways. Please use includes()"
Dev: "I'd rather stick with something I know will work"
Resistance to change comes in many forms
ten24 · 7 points · Posted at 22:33:17 on April 26, 2018 · (Permalink)
And they might be right. How well do you know your users? Software use-cases vary widely. There are most certainly win 9x systems in use today.
But his point isn't that it might break things for win98 users, it's that the code that ostensibly fixes a win98 issue might also, incidentally, be covering a bug that's still active in win10. So by removing it, you'd uncover that.
In which case I'd say the reasonable thing is have a testing environment and/or a set of test criteria by which you evaluate releases.
So to s-mores, I'd say the response would be "let's try taking it out and run some tests on issues that this code could conceivably raise, and if they pass, we'll ship it. If something else comes up, we'll re-introduce it, or better yet find a more robust fix". It's ok if it breaks things, as long as you have a backup plan.
Xaxxon · 1 points · Posted at 23:17:14 on April 26, 2018 · (Permalink)
This is what CI is for. If you don’t have that then the reaction is a good initial reaction.
And then they do comment, but it's in another language so whenever you want to read a comment (or even a variable name) you have to run it through google translate...
pdp10 · 1 points · Posted at 23:16:46 on April 27, 2018 · (Permalink)
I have a rule that a comment in another language is acceptable when the alternative would have been no comment. Assuming your toolchains can handle UTF-8 in code, that is.
I was lucky in that it was still in the Latin alphabet.
Overall, not too different to reading uncommitted code; it was ancient legacy code, and that was the main thing I had to struggle with, not the language - which I did run through google translate at points, though it didn't turn out to be very helpful.
I think that too many people think that when they're told to comment their code they're supposed to describe what the code is doing. And so the balk because, why should they describe what the code is doing, just RTFM! What they don't understand is that the reason you comment code is to describe why it's doing what its doing. So that when you come back in 6 months and go "why the fuck would I do that" you know why. And if you have to make another change you don't revert all the little kludges and fixes
I don't even write comments for other people. I write comments for myself when I inevitably have to go back to a script I wrote n months ago and have completely forgotten whatever esoteric kludge I had to do to get it working. Ah yes the credential passthrough doesn't work on the third Sunday of every month which means the letter 'a' gets dropped from every other sentence in the log file, that's why this fix is there.
I often don't have the luxury of using anything except the framework or library handed to me by the software creator. When it comes to "smelly code" verbose commenting is just part of the deal. I get it working and move on, life's too short.
I absolutely agree with you. Anybody who can remember why they did every little weird, kludgy, bizarro thing they do is absolutely fooling themselves. I barely remember what I did this morning, let alone 10 months or 10 years ago.
A lot of coders straight-up don't believe in commenting code, and actively argue against it. (Let alone doing any of the other helpful things you suggested) They fervently believe comments are a code smell, because all methods should be short enough and descriptively enough named that their intention is blindingly obvious. And even when that's not the case, and a comment would be useful, they stick to their "comments are bad" mantra.
fwiw I subscribe to that mentality, more or less. My thought is that comments shouldn't need to say "what" code does, but rather should say "why" the code does what it does. I think that the people to whom you refer don't draw that distinction, unfortunately, and just blanket say all comments are bad full stop.
I’ll never understand not commenting at least blocks of code.
Even just:
/* Get data. */
/* Massage it A. */
/* Massage it B. */
/* Turn it into a tree and return. */
Now everyone, especially you, can skim read the code and understand where and what it is doing/supposed to do. And dig further at each section if required.
The comments are practically micro architecture.
But hey, I’m inspired by LEGO instructions.
pdp10 · 2 points · Posted at 23:12:55 on April 27, 2018 · (Permalink)
A lot of coders straight-up don't believe in commenting code, and actively argue against it. (Let alone doing any of the other helpful things you suggested) They fervently believe comments are a code smell, because all methods should be short enough and descriptively enough named that their intention is blindingly obvious. And even when that's not the case, and a comment would be useful, they stick to their "comments are bad" mantra.
Ah, the "Uncle Bob Defense". In "Uncle Bob" Martin's Clean Code, it's said that good code usually doesn't need comments because it's written so clearly. In their search for a justification for their aversion to comments, the misguided coder seems to convince themselves that because their code doesn't have comments, it must therefore be good code.
The answer to this fallacy is always Why, not how. That workaround doesn't need a comment telling me how it works, it needs a comment telling me which browser is affected and a link to upstream's bugtracker so we know how to determine when we can delete the workaround.
A lot of coders straight-up don't believe in commenting code, and actively argue against it. (Let alone doing any of the other helpful things you suggested) They fervently believe comments are a code smell, because all methods should be short enough and descriptively enough named that their intention is blindingly obvious. And even when that's not the case, and a comment would be useful, they stick to their "comments are bad" mantra.
They're not entirely wrong. Only mostly so ;)
The thing that people who think like this are missing is the purpose of comments. You don't need to document what your code is going and you should not; just document why it's doing that.
I can see that you're calculating the square root of the 17th field of the getEventInfo() return value. But I don't know why. Why's it the 17th field and not the 18th? Am I sure that you didn't make a mistake when choosing the field to use? Where's the API spec that describes what all the fields are?
Unless they write method names like LoadLibraryWrapperForWindows95Support__TODO__RemoveWhenWindows95ReachesEOL(), then their methods are not named descriptively enough to remove the need for explanatory comments.
Those hacks and kludges need to be documented, associated with their cause, and forwarded to the manufacturer of the issue. When the issue is addressed they need to be revisited, or if not followed up on.
Those hacks might be for something that's not in your power. For example, we have workarounds for operating system bugs, or for security / maintainance software or for God knows what. Sure, those got fixed, but there is always that one important customer that will not update so that workaround is there forever now.
I’ve started sending back PRs if they do something weird and don’t leave a comment. They’ll often have a good reason if I ask why they used a weird solution, but it’s so easy to put that as a comment! In a year’s time they won’t have a clue what that weird bit’s for.
[deleted] · 1 points · Posted at 09:28:03 on September 21, 2018 · (Permalink)
Saved. Kludges can't be avoided entirely and this is good solution.
kbotc · 3 points · Posted at 04:01:24 on April 27, 2018 · (Permalink)
Yea, but once Windows Vista came around the LoadLibrary code now causes a random segfault and requires UAC for almost unexplained reasons: You built up 30 to 40 of these edge cases in the 450 line function and now you need to move forward but are stuck by legacy requirements and they layer on each other. You pull out LoadLibrary, but someone thought it was a good idea to depend on the return value of that somewhere else deep in code "Because performance." Now you have to go back and try and understand a coding methodology that was in vogue 25 years ago. All to support Windows 95.
But sometimes old code does really suck and needs to be thrown away..
mughinn · 10 points · Posted at 18:36:22 on April 26, 2018 · (Permalink)
He addresses this though
When programmers say that their code is a holy mess (as they always do), there are three kinds of things that are wrong with it.
First, there are architectural problems. The code is not factored correctly. The networking code is popping up its own dialog boxes from the middle of nowhere; this should have been handled in the UI code. These problems can be solved, one at a time, by carefully moving code, refactoring, changing interfaces. They can be done by one programmer working carefully and checking in his changes all at once, so that nobody else is disrupted. Even fairly major architectural changes can be done without throwing away the code. On the Juno project we spent several months rearchitecting at one point: just moving things around, cleaning them up, creating base classes that made sense, and creating sharp interfaces between the modules. But we did it carefully, with our existing code base, and we didn’t introduce new bugs or throw away working code.
A second reason programmers think that their code is a mess is that it is inefficient. The rendering code in Netscape was rumored to be slow. But this only affects a small part of the project, which you can optimize or even rewrite. You don’t have to rewrite the whole thing. When optimizing for speed, 1% of the work gets you 99% of the bang.
Third, the code may be doggone ugly. One project I worked on actually had a data type called a FuckedString. Another project had started out using the convention of starting member variables with an underscore, but later switched to the more standard “m_”. So half the functions started with “_” and half with “m_”, which looked ugly. Frankly, this is the kind of thing you solve in five minutes with a macro in Emacs, not by starting from scratch.
Or, it could have been written to maliciously prevent understanding, in an attempt at (unearned) job security. I had this for a consulting client, a major, international electronics manufacturer, who's entire radiation-hardened production process was managed (both technically and administratively) through a huge program written entirely in VB5.
The developer did the following, very intentionally:
Used only single-letter variable names everywhere.
Not one comment anywhere.
No written documentation.
Almost no code factoring. Rather than define subroutines, he just copy/pasted code (one of the reasons it was huge).
And the coup de grâce: he didn't use the visual designer for forms at all. There were no visual elements in the designer for his UI. Instead, he created each UI element in code, and positioned it manually on the page - kind of what the older code-behind stuff did in ASP.NET, but all of this was manual. And remember, only one letter variables, no strong typing, reuse of variable names therefore everywhere, for any type of object at any time.
He was entirely hostile to my project, which was to "fix" it. Luckily, the client agreed to a complete rewrite, which was accomplished along with a full suite of new requirements analyses. user interviews, etc. As it turned out, the system had been so flawed, that almost nobody used it as intended, but minimized contact with it, resulting in unpredictable results in production runs, inability to correct problems, etc. - but then, using the original software apparently didn't make that any better.
Edit: Also, no source code management, no issue tracking of any kind.
These problems can be solved, one at a time, by carefully moving code, refactoring, changing interfaces.
I think this is only somewhat true. You can definitely change individual things. But with the inertia of the large codebase, there's only so far from its original architecture that you can walk it until you're talking about the same amount of effort as a rewrite.
I think sometimes a rewrite is a good decision. It shouldn't be a clean-room rewrite though. There should be constant reference to the original code to account for compatibility and so as not to lose valuable things that were in the original code base.
I don't see that he's addressing a number of valid reasons to go full rewrite.
My company did a rewrite, it was costly in terms of money, sanity and customer goodwill, but it's the only way there's a decent future for the product. We had a number of factors, among them :
It was written in PHP, as the first post-college project of someone with no experience. Nobody working on it now things PHP is a particularly good fit for the product and in fact the new requirements of the product are not effectively supported by PHP tooling that is familiar to any of the present dev team. Post rewrite it's in JS/Typescript on Angular and Loopback.
It was written a very long time ago and maintained by a long thin string of developers that communicated little with the next person in line. In fact it was a strain of employees at the contractor that was responsible for the initial design.
The mobile component of the system was done in native code using custom libraries by a contractor that was uncooperative and effectively hostile to us and the first set of(better, more involved and trustworthy) contractors. Moving it in house would take longer than a rewrite, very likely.
The business had changed. The original design had limitations of scale, usability(at scale) and cost-effectiveness with respect to resources. The product wasn't paying it's own maintenance costs and was unappealing to larger clients due to it's simple UI that couldn't effectively manage larger data sets. Our new plans were not easily compatible with the existing system and some goals had hard conflicts with the existing model.
Precisely 2 people out of the 8 or so that contributed to the rewrite were deeply experienced with the old system or very knowledgeable about the tools used in it's creation. We're a small business working with a still-smaller web-development startup. The available expertise for the old tools vs the new was obviously slanted and causing everyone to learn the old tools implied additional costs for literally no value.
A bad fall season(we're tied to schools) caused us to leak an incredible amount of customer goodwill, essentially with our hands tied due to the mobile-app contractor arrangement. We could *not* bear another season like that, personally, as a business or even on a moral level since PTOs were pooling cash to purchase our product and getting grossly embarrassed in front of a bunch of kids.
We contracted the trustworthy dev team(and myself, the first internal dev/IT person) to rewrite the application from scratch on new technologies with an eye to supporting the new goals, new use case and new scale. We x'ed out the the bad contractor completely and rewrote their component on a new platform. I'm now the sole dev doing regular work and it's manageable.
We did the work in a summer and had a really rough fall breaking in the new product but by no means would I trade it for the idea of trying to piecemeal change the old application.
I think given the right set of circumstances there really is a case to be made for getting rid of old, obsolete, ill-designed code. Perhaps it's only on the far edge cases, but Spolsky doesn't seem to acknowledge any such thing. Instead he dogmatically asserts that you should slowly creep projects over. If we had done that the new project would be a quivering mass of little links to the old system and we'd have basically all the same problems because the fundamental design was no longer valid.
p1-o2 · 1 points · Posted at 21:10:10 on April 27, 2018 · (Permalink)
I've been through this twice now as you described. That's a case where I'd have fought for a refactor as well. Especially with so much of the team being more familiar with new tooling.
I recently had the joy of trying both ideas out at the same time actually. We had half the team do a full rewrite of the code-base while half the team fixed up the old code. We ended up with two copies of the reworked product in the same amount of time (1 year), but the new code-base was still far more robust even if they were functionally the same.
I think not being shackled to assumptions and models that are no longer valid( if they ever were, sometimes the first design was just bad) has a lot of benefits. Moreover designing around new technologies from the start rather than emulating old behavior and then integrating new features is a very different experience. I did both on this project.
p1-o2 · 1 points · Posted at 22:45:58 on April 27, 2018 · (Permalink)
Agreed, thanks for sharing your experiences! And GL down there in the underdark. ;)
Heh, sometimes. I forget my username, had me confused for a moment.
I just immediately take a skeptical stance when any person, even one as skilled as Joel Spolsky, makes broad sweeping statements about complex topics, doubly so when they suggest that the least regrettable choice my company has made with our software was some grand snafu.
I want to add that without a rewrite we very likely would never have had the buy-in from management to get the appropriate manpower on the job. The idea of a whole new world of possibilities is how we contracted an outside team, trying to part it over would never have gotten the manpower necessary to do it before the product choked and died.
And when that happens, management's so used to hearing that the code sucks and needs to be thrown away that they'll ignore any valid justifications for doing so.
Yeah, that's the problem with crappy code. You think that there's nothing wrong with it because it's been tested. But how do you know? Nobody apparently understands the code. Often, code is so bad that nobody knows how buggy it is. Look at OpenSSL, for a public example.
The idea that just because code is in production means it must work is a logical fallacy. Not all code in production works. Sometimes it's just not reported as a bug. Sometimes people don't realize it's a bug. Sometimes people find workarounds to accomplish what they want without reporting it. Only when none of those things are true do bugs get reported (most of the time).
There's plenty of shit that has gone wrong that people don't even realize is wrong. If you don't know it's wrong, why would you report it?
I worked for a project that one step of it was to edit an existing page on a web application and apply new rules to it. One of the things I decided was better off was to rewrite the whole thing, because it was shit (it was). In the process of researching how it was working to know how to rewrite it, I learned that it never worked right in the first place. It was a request approve/deny system where there was both manual and automated denials (based on different scenarios). All manual approvals and denials were counted as approvals. All of them. Only automated denials ever got treated as denials.
No one ever noticed, because one team approved/denied requests, and a completely separate team handled the results of those approvals/denials, and these teams never coordinated anything. The requesters wouldn't report anything because nothing appeared wrong as the bug always worked out in their favor. So how would anyone ever notice there was a discrepancy? This page was in production in an incorrect state for over ten years.
The point of this story is to prove that this entire concept that, "It's in production and no one complains, so it must be working," is plain wrong. It's very easy for people to not realize something is wrong. No one would have ever caught this bug if I hadn't done a top down analysis to rewrite it.
The important part about refactoring your own code and rewriting it is to know when it's appropriate and when it's not. If a full rewrite is going to give little benefit and take a long time, don't do it. If it's the fifth or sixth time you're doing it, don't do it. If you don't know anything new that would provide benefits at the core of the rewrite, don't do it. But you also have to know what you're doing if you're rewriting it. If you're going to rewrite it by doing something completely different, then it's probably not going to be beneficial unless what you're doing has already been done elsewhere and has been successful.
sevl · 40 points · Posted at 17:33:56 on April 26, 2018 · (Permalink)
if that was in production for ten years and nobody ever had a problem the requirement itself was not needed. during rebuilding the requirement for manual approval should have been reevaluated
The manual approval requirement scenario required a human element and the automated did not, but were two completely different scenarios that would lead to approval with different approval time windows. It was absolutely required.
It was a bug that no one caught because no one did a cross analysis between what the team that was approving requests manually did and what requests were acted on as if they were approved. Everyone assumed that it worked because it was in production. That doesn't make the requirement invalid. It just furthers the idea that "In Production does not mean 100% working".
The real question, is that after 10 years of working wrong and you fixing it, was there any actual real benefit to the business, in terms of dollars or efficiency, or any other metric you choose.
Or was the requirement met and some manager someplace could check a box.
It's really not that hard to see the problem. No one noticing the problem doesn't mean the problem isn't having a drastic effect. If there were rounding errors to interest, no one would notice it easily. But an audit after 10+ years on something like a mortgage, or savings account, and there would be quite a difference. I really, really hate software teams who lean so heavily on the idea that no complaints means everything is good. I can understand dev work prioritization being somewhat based on active complaints from more important customers, but what managers tend to overlook in these situations is that the unnoticed terrible bug can be noticed at ANY point in time and if/when it does, it'll look worse! Even if I could tolerate an initial release with such a mistake, knowing it's been around for so long with the same dev team also means an engineer or two, or three, has noticed and probably brought it up to a manager who de-prioritized it. That alone would make me stop working with said team if I was on the customer side. It immediately tells me the quality of their engineering.
Actually, yes. The bug fix related directly to payments they shouldn't have been making but were.
The rewrite was going to happen anyway, though. The old page was such a mess it probably would have taken more time to add the new requirements into it than starting from scratch anyway.
jk147 · -1 points · Posted at 18:38:16 on April 26, 2018 · (Permalink)
It may mean more efficiency, but in terms of dollar per benefit def. a no. Creating a whole new thing for an edge case is counterproductive.
Not to mention the possibility (almost certainly) of introducing new bugs with an overhaul.
sevl · 14 points · Posted at 17:57:49 on April 26, 2018 · (Permalink)
so in 10 years there was never a case where an approval was questioned, where someone asked the approver why something was approved where an approver got in trouble for the false approval? there was never any consequence to an approval which should have been a denial? why then would you need the possibility to deny at all?
They didn't question it and just took it for fact, because it was two completely different groups that handled the acceptance/denials vs the group that actually acted on the accepted requests. Since it was two different groups that didn't coordinate at all, no questions about the approved requests were ever raised and they were just assumed as correct.
kntx · -1 points · Posted at 18:56:01 on April 26, 2018 · (Permalink)
I think the point isn't that production code definitely "works", but that production code often has had many (potentially undocumented) use cases/bugfixes added to it over time. These use cases are hard to transfer in a rewrite.
That's the point of User Acceptance Testing (UAT). The users will try to use the new version exactly the same as the old one. They know what should or shouldn't work based on the context of the old application combined with the new requirements. If they were able to do something in the past and now they can't (or, were not able to do something and now they can), they'll call it out. If you don't have a good reason for it, you know you missed something.
QA has a purpose in that their job is to make sure that the application is designed the way the requirements say they should be, while UAT's purpose is to make sure that the requirements and resulting application actually fit their real world use cases.
When you're redoing an application, UAT isn't new users, it's users that have been using the old system for as long as possible. That gives them the ability to catch and call out these unknown use cases because they were likely there when they were first implemented and know the reason behind it.
I've never seen a set of UATs that capture ALL cases - there are simply too many use cases to justify detailing each one w/ all possible input combinations.
It sounds like your actual users do UATs, is that true?
Typically I have my product managers run the UATs, because my end users expect any software we release to be fully QA'd. That being said, we do have a beta stability period, where beta users have a chance to report bugs, but even with hundreds of beta testers, I still find that some use cases don't get completely tested.
UATs are supposed to capture all functionality in theory, but in practice I've never seen it happen.
jadero · 1 points · Posted at 21:22:14 on April 26, 2018 · (Permalink)
Most people treat computers as either infallible or useless. Neither attitude will get you good bug reports.
Most of the time you don't even need good bug reports. You just need bug reports in general. If you release something and there are no reports at all you will assume that everything is working as expected. The problem is what you expect and what the user has come to expect may not be the same thing.
jadero · 1 points · Posted at 21:34:02 on April 26, 2018 · (Permalink)
Sometimes people find workarounds to accomplish what they want without reporting it.
Or just puts a comment on it because they can't change it because it would break code that uses it. My favorite example, I wish I'd saved the link, is a function in the .net api that looks something like,
void DisableTheThing()
// Enables the thing
Yeah, it "works", but it's undeniably bad code.
Pomnom · 0 points · Posted at 16:18:31 on April 26, 2018 · (Permalink)
There's plenty of shit that has gone wrong that people don't even realize is wrong. If you don't know it's wrong, why would you report it?
So then who should be the judge of whether it's a bug or not?
The people who wrote the requirements and set up the use cases for the end product. But no one is infallible, mistakes happen all the time. Explanation of the full requirement may have missed a scenario or the testers may have improperly tested. However, if the result appears to be as expected from a user interaction side, then it won't ever get reported once it hits production. That doesn't mean it's correct, nor does that stop it from being a bug.
The whole point is that the first time you make any system, you don't know what you're doing. Every decision has a non-zero element of speculation.
Yes, yes, I don't care about the technical details, I just need an estimate from you before the end of the day.
┻━┻︵ヽ(`Д´)ノ︵ ┻━┻
I got dinged before from telling people something wouldn't work the way they wanted and not giving details until asked to explain... this happened enough that I started preemptively explaining the details behind the problem so they'd understand it....and then got dinged for getting too deep into the minutiae.
optomas · 25 points · Posted at 18:50:16 on April 26, 2018 · (Permalink)
"How deep you want to go?"
I ask this a lot.
You can either trust me (If I say it doesn't work like that, it's because I've tried it, probably hundreds of times and watched it fail) or sit through an explanation.
"Yes fluid is relatively incompressible. Do you think this means it is perfectly rigid? Do you want to see the equation for volume loss in relation to pressure? The keyword is 'relatively', not 'incompressible'."
Nope, common misconception - old windows often (not always) have the thick part on the bottom because the person who put it there put the bigger end on the bottom, like ya' do.
Technically, they're an "amorphous solid", but they don't "flow" really slowly like say, pitch (unless you melt it).
You should try Scrum! It's so awesome! It's an entire gamefied methodology where you assign random numbers (that sort of represent time estimates) to stuff before you are able to investigate it and actually accurately assess how long it might take!
mcmcc · 127 points · Posted at 14:25:35 on April 26, 2018 · (Permalink)
“Hence plan to throw one away; you will, anyhow.”
"If you plan to throw away one, you will throw away two."
"If you plan to throw away one, you will throw away two."
"If you don't plan on throwing at least one implementation away, then you're a bad planner."
About the only exceptions I've seen is where you know the problem domain so thoroughly that you have already solved everything in it multiple ways, either because of expertise or simple problems.
Anyone who claims it should be done otherwise should be immediately labeled as not knowing what they're talking about & their opinions heavily discounted.
mshm · 39 points · Posted at 16:30:56 on April 26, 2018 · (Permalink)
Managers should plan to throw away code, developers should develop like it's the code to be delivered.
Unfortunately, if the developers were to treat what they’re developing as the shippable product, and it is thrown away, then they are typically also thrown away because, fuck those losers that produced the shit we had to throw away! (It was them, not us!)
Then a new team is brought in... and the same mistakes are made all over again, because all of the learning - the actual value produced by the throw away system - was thrown away with the developers.
jboy55 · 5 points · Posted at 19:35:58 on April 26, 2018 · (Permalink)
Typically this ends with bankruptcy of the company as well. But other shades of this are the old team is still there, ‘they’ label their code as legacy and the new team is taught to ignore the old team/code in case the old ways infect the new ways. The new team is often already in the building but was just spectating from the sidelines. And then there was Joe... and Sue and they were in all of my 11am meetings and never said anything until that fateful 3pm Friday meeting when the knives came out....
I mean, there were a lot of edge cases in the old code that need to be respected.
mcmcc · 25 points · Posted at 16:08:13 on April 26, 2018 · (Permalink)
The moral here is that you often miss out on important information if you don't make an honest effort in producing a fully viable implementation.
Proof-of-concepts are great as research tools but they are typically not substitutes for "real" implementations.
POC is almost always for something like demonstrating the use of a new tool, or exploratory work in applying it to your domain. when i do them, they're deliberately not deliverable, but produce good patterns for using the tech in the actual product
I dunno, the last POC I did was a test to see if a technology switch was going to get us the improved performance we needed on what we were developing. I took the worst performing chunk and rebuilt it in a new technology to see if we would get the desired effect. If I didn't build it fully and honestly, with the intention of it getting released, it's not a true POC for that ideal. Plus, if approved, the entire idea would would become the foundation of the project as we migrated over (the piece in question wouldn't get done a third time), so if the foundation was shit ultimately I would have made things worse.
If a POC is just a, "Look at what we can do with this!" I totally agree, but there are multiple different varieties of POCs.
Xaxxon · 1 points · Posted at 23:25:16 on April 26, 2018 · (Permalink)
Experience simply shifts the threshold of what is too complex to predict.
What designs are just “obvious” because you “know” they will be bottlenecks later vs when to just write the simplest, naive code.
I actually just take it a step further and reformat my computer fresh daily. Helps clear my head before work having to reinstall Windows and partition all my drives.
This reminds me of someone I was once unlucky enough to work with who said he regarded all his code as temporary and throwaway, because “managers will always make you throw it away before you have a chance to make it good.” So why bother making it good, he reasoned?
I thought he must have been damaged by bad experiences with stupid managers. But no, turned out he was just an idiot.
Worse, once he got some management responsibility he started cancelling other people’s projects at random to “teach” them how the world really works.
Rewriting is not a unicorn, and often leads to a million of other problems. There is so much knowledge and testing that has gone into making something perform properly in production. I have never experience or heard about a test suite that captures all of this. This will be thrown out the same second you rewrite everything.
What the mantra means is write a prototype that models major components and their interaction. Then you learn a lot and can start over again. This prototype can be made in a fraction of the time needed to complete the project, and it’ll save time at the end. If something is close to production ready it’s not a prototype, and gradual refactoring is preferable.
dsk · 54 points · Posted at 15:29:10 on April 26, 2018 · (Permalink)
Insights from making the first system mean you can make the better decision without speculation the second time.
This is the exact reason why you should rewrite code only as a last resort, because you won't know what you need the second, third, and fourth time around either. The longer lived your 'first' codebase is the more this fact is underlined.
Worse for you, your original code will have a massive amount of secret (i.e. unspecified) functionality that was implemented as part of bug fixes, maintenance patches, module rewrites, etc. etc. etc. This functionality builds up over years or decades. A clean rewrite guarantees you will fuck things up all over again, partly because you will miss all that 'secret' functionality you didn't know was there, and partly because you will just fuck things up in new and inventive ways - because what makes you think you're any smarter than the guys in your position who wrote the initial code?
And I speak with some experience. Some of my good friends are developer who were involved in a ground-up rewrite of a legacy C++ application (90s era+) in Java. And believe me, they are smart and talented developers writing really technical code. The project took 10 years (10!) and in the end, they didn't even manage to match the feature set of the original. In the meantime, the product completely stalled being in maintenance mode with no major new functionality and fell behind their competitors. The alternative, of course, was not to do a ground-up rewrite but rather update the code incrementally, module by module - with each module released and get battle-tested in production. They agreed.
This is a horror story that is repeated all the time, and developers never learn. They always think they can do it better a second time.
Yeah, that's the problem with crappy code. You think that there's nothing wrong with it because it's been tested
Because it works.
And nobody is arguing against partial rewrites of specific modules. You can do that. It's the ground-up total rewrite that is almost always a total and utter disaster.
People like clean, simple code because it's obvious that it doesn't have problems.
Great attitude to have towards utility scripts. Doesn't really apply to applications with hundreds of thousands (millions?) of lines of code, written over years (decades?), and used in production by hundreds of institutions and hundreds of thousands of users.
Trust me, your 'clean, simple code' is going to look like shit to the next guy who comes over or after a few years of bug fixes and maintenance.
your original code will have a massive amount of secret (i.e. unspecified) functionality that was implemented as part of bug fixes, maintenance patches, module rewrites, etc. etc. etc. This functionality builds up over years or decades. A clean rewrite guarantees you will fuck things up all over again...
I was looking for a comment like this, and a related point: that practical problems have a lot of subtle complexity, which has been encoded (hopefully) in mature code. A clean rewrite always seems nice because we tend to be ignorant of all the details until we're faced with them one by one.
On the other hand... mature code which has these subtle details (unclear in code, and uncommented, or worse: untrustworthy comments) sucks to work on because it's volatile under changes. This is where the modular rewrites you're suggesting are great, so you can clarify and improve parts of the code while still interacting with the bulk of the system -- and not failing regression testing.
And one of the first goals of the refactor should be the minimum to get the code into a state where it can be tested. Then write those tests and start documenting / uncovering your assumptions about how it works now.
That way, when tests break you can decide:
Okay, the way it worked before was broken, let's fix the test. And indicate this behavior change in the release notes.
Oops, when we refactored we forgot about XYZ. Good thing we caught it prior to release.
Worse for you, your original code will have a massive amount of secret (i.e. unspecified) functionality that was implemented as part of bug fixes, maintenance patches, module rewrites, etc. etc. etc. This functionality builds up over years or decades. A clean rewrite guarantees you will fuck things up all over again, partly because you will miss all that 'secret' functionality you didn't know was there, and partly because you will just fuck things up in new and inventive ways - because what makes you think you're any smarter than the guys in your position who wrote the initial code?
At my last job I did a small-ish (10k LoC) port/rewrite and ran into this, but I was lucky in that it was a service that only did a single thing and had a single JSON=>JSON interface, so it was possible to run logged messages through it and see the discrepancies.
Anyway, I ran into a lot of these edge cases, but one of the things that became clear was that the majority of these edge cases were not actually important and we ended up dropping them in the port.
Doing the actual rewrite wasn't so bad, testing it to ensure it did what we needed took up most of the time.
dsk · 12 points · Posted at 16:10:03 on April 26, 2018 · (Permalink)
At my last job I did a small-ish (10k LoC) port/rewrite and ran into this
I suspect that people who clamour for rewrites in this thread have codebases of that size in mind. The thing is, nothing I argued really applies to projects that small. A rewrite of 10k LoC isn't particularly difficult for dev teams of any size to attempt. So go nuts - rewrite as much as you want.
Things get real hairy when you have applications with hundreds of thousands or millions LoC.
I work in FPGA design engineering. The testbench master controller for one of my designs is a 10k LOC monstrosity that takes in a custom command structure specified by our simulator. It is scary complex and really needs a redesign. But no one will ever do that because it's scary.
[deleted] · 23 points · Posted at 16:16:18 on April 26, 2018 · (Permalink)
People like clean, simple code because it's obvious that it doesn't have problems.
Isn't this part of the arrogance (or perhaps, naivete) that the author is describing though?
This idea that "clean, simple code" obviously doesn't have problems because it is clean and simple. When it may very well be missing a myriad of edge cases that it didn't account for at all and the reason the past code is so messy is because it made the very same mistake and had to be added to incrementally, making it less clean and less simple over time, but also more capable of handling circumstances that no one was likely to think of at the offset.
I'm sure this is not always the case, but it seems plausible that it could be the case in some situations.
The argument is that you could turn that messy code into something clean by rewriting it, while maintaining functionality.
Sometimes we think one strategy or pattern is the right one to use, and then 6 months later we find out that we absolutely wrong. Rewriting that code with a different approach can simplify a lot of the mess.
Often it can. However justifying business value for refactoring code to be clean, simple code - which is already working in all given situations - is super tough.
[deleted] · 1 points · Posted at 18:52:58 on April 26, 2018 · (Permalink)
It seems the argument of the article though is specifically about business/competition/cost and how much time you can waste in trying to start over from scratch. Rewriting piece by piece, or rewriting completely in your personal time is, I'm sure, a different story.
For anyone as confused as I was, apparently "Space Station 13" is the name of a role-playing game. "Gas" is the name of something in that game, and "gas defines" are define-style pre-processor macros in that game related to gas somehow.
Rewritten with that in mind (and some context from the link):
In the game Space Station 13, the order of operations used to calculate plasma's burning temperature was wrong for 15 years because of define-statements.
And for people like me who couldn't see what the problem was at first:
The macros used to be #define value a + b, which would simply insert a + b wherever it was used, allowing for other operators in a statement to take precedence over the addition sign. The commit changes them to #define value (a + b)which forces a + b to be evaluated first in any arithmetic where it's used
In describing C code, define is used as a noun. “Sorry, I used a define” or “Glad I got rid of those defines at last.”
It’s a preprocessor statement that does a kind of crazy search/replace in the subsequent code, without any observance of the rules of the language, because it’s done before the true language parsing takes place.
FreePascal has a bug in generic unaligned memory move that was just discovered.
Luckily for x86 a different, more optimized assembly function is used, but on other processors that need correct alignment this breaks everything in every freepascal program for 11 years.
This article, and a few other reasons, are why I stopped reading spolsky.
He’s chock full of strong opinions, but he’s really not grown as an engineering thought leader.
The points you make are totally valid. Countless times we’ve had to dive into systems that have been patched and repatched by various sets of engineers, none of whom has any great sense of ownership over the system. Ie they wrote code with the goal of pushing out the product, not with the intention of building a resilient piece of software.
In every such situation, shortcuts were taken and then patched over, usually with other shortcuts.
Spolsky glibly ignores that this is the actual reason why engineers want a rewrite - a rewrite means they can basically start fresh and actively avoid the mistakes made over many iterations of the system. He’s never been one to rethink his perspectives, looks like after all these years of no longer being in the limelight he still sticks to what he knows.
You realize this article is almost 20 years old right? I'm not sure criticizing him for not rethinking after all these years is accurate for such an old post.
Sounds more like knee-jerk reactions of programmers proving his point; it is easier to write than read, and they'll defend rebuilding a house to move a door.
It was as incorrect 20 years ago as it it is now. There are multiple cases when the code actually sucks. Yes, sometimes what is perceived as bad code is there because there's no obvious way to make it good, it handles obscure edge cases and business rules. But sometimes it's pretty clear that people who wrote the code had no idea how to write good idiomatic code and just banged on it until it kinda worked.
The fact that he hasn't recanted makes me assume he still believes it.
daV1980 · 55 points · Posted at 15:40:02 on April 26, 2018 · (Permalink)
Ie they wrote code with the goal of pushing out the product, not with the intention of building a resilient piece of software.
That is because the product is the goal.
No one else cares how clean and beautiful a piece of code is that has zero users. It's irrelevant.
Code for most purposes isn't written in a vacuum, it's written to provide functionality to someone or something. Pushing down technical debt isn't valuable in itself, it is valuable because you believe paying it down will allow you to deliver more and better value to people.
gpyh · 22 points · Posted at 16:41:36 on April 26, 2018 · (Permalink)
No one else cares how clean and beautiful a piece of code is that has zero users. It's irrelevant.
But it does not have zero user. Once you have such a product that you need to maintain and make evolve, every new feature is an uphill battle. Your velocity decreases to the point where your competition is guaranteed to catch up with you; a rewrite is the only viable option.
However I do agree with Joel here: you don't need to rewrite the full product. You can rewrite the most critical parts of it and incrementally make it better.
This is a major point in the article and somehow it seems like many top comments are missing it
phySi0 · 1 points · Posted at 13:15:48 on May 10, 2018 · (Permalink)
But someone did make the point that the article is attacking a strawman, anyway, because nobody who advocates for a rewrite says, “let's throw the whole codebase out and start from scratch”, rewriting bits at a time is already what the rewriters are saying.
nobody who advocates for a rewrite says, “let's throw the whole codebase out and start from scratch”
I've heard people say that many times. When I was less experienced I would say that myself too. It's been a while since I read the blog post but I'm pretty sure there are examples major companies making this exact mistake. This is not a strawman. Rewriting bits at a time is what some rewriters are saying but definitely not all of them.
It's why it's valuable to have 2 major stakeholders in management for a project.
One for saleability (the product itself)
One for maintainability/correctness
There's many times in the lifetime of a product where you have to decide whether to ship with known bugs, or wait til they're fixed. If you're too heavy on the one side, you're never getting your product to market. If you're too focused on getting features out, you're going to end up with a pile of garbage that takes so much longer to add new features.
As to the article, I feel like people missed the latter half of it. You can maintain and fix stuff without throwing it what exists wholesale. Some of it will be very close to a rewrite. You will re-write parts of the code. But starting completely from scratch? That's just asking for delays after delays.
No one else cares how clean and beautiful a piece of code is that has zero users. It's irrelevant.
That's not even close to true.
Clean code is a million times easier to maintain, and "beautiful" code is easier to understand. If I write an hard to maintain piece of shit, when it comes time for a maintenance programmer to come in and fix some bugs, they're going to have a shit time and end up doing the worst thing possible: ineffective workaround. Instead of fixing the code at its core, they handle the result of the broken code. It's a HUGE issue. Any hope of efficiency is thrown out the window right then and there.
Another issue with code that is not easily understood (aka ugly) is when it comes time to update something common or make minor modifications that could benefit everyone, instead of working with what's already there and adapting it for everyone, they will duplicate the entire file, make their changes, and apply it only to their work because that's the only way they can ensure it doesn't break something (as everything else is too complicated for them to be sure it's doing what it should be). This results in tens to hundreds of files that are identical except for minor pokes and prods in different locations. As someone who came on to a project late with a fuckton of this, this is a nightmare to figure out, maintain, and above all else, fix. It makes matters a hundred times worse.
Clean and beautiful code has a purpose, a long term purpose. As long as you don't overdo it and spend way too much time on it.
sirvesa · -2 points · Posted at 15:51:31 on April 26, 2018 · (Permalink)
Spolsky glibly ignores that this is the actual reason why engineers want a rewrite - a rewrite means they can basically start fresh and actively avoid the mistakes made over many iterations of the system.
But he doesn't ignore it. He challenges the assertion that version 2 will magically be mistake-free; that the reduction of mistakes/improvements will be worth the opportunity cost of the rewrite.
Put another way, yes, a lot of code/systems are so costly to maintain that a rewrite is called for, but it's less often the case than many engineers think.
this is the actual reason why engineers want a rewrite
It's an actual reason, and you're right to say that Joel ignores it, and his article is the weaker for it. But I can't accept your claim that it's the actual reason -- that's just as unhelpfully black-and-white as Joel's statement.
The reality is that it is some combination of the sound reasons you give, and the naive or self-serving reasons Joel gives, that produces any rewrite decision. It's not always easy to gauge how much of each component there is, and there's very often significant amounts of each.
Yeah, he's completely misinterpreting the mantra. You're supposed to build one and throw it away immediately once you understand the domain, not maintain and use it for years accumulating a bunch of domain knowledge in the code and then throw away all of that and build a new version with people who didn't build the original version.
boot20 · 4 points · Posted at 17:58:31 on April 26, 2018 · (Permalink)
Well, that and the perception that those coders didn't know what they were doing and I'm a better coder.
Many times the older system is fine it's just a massive pain in the ass to get into somebody's mind and figure out why they made certain decisions.
People like clean, simple code because it's obvious that it doesn't have problems
We sure do. And the odds of the fancy new rewrite being that "clean, simple code" that everybody loves? Not good.
I mean, not for the coders of r/Programming of course. We're all amazeballs and write perfect code every time. Just ask us. But for everybody else, the odds are not good.
We sure do. And the odds of the fancy new rewrite being that "clean, simple code" that everybody loves? Not good.
It depends. I've seen basic CRUD web applications written by people who didn't care to learn the idiomatic way to code with the chosen language and framework. Rewrite made them way better.
As a graphic designer I can tell you when I worked at big...HUGE online company the amount of “gross looking,” code was amazing.
Programmers would say “I don’t need to comment if the code is clean enough.”
This is true, but after 500k lines of code and backwards patches it all looks like spaghetti.
And old programmer once told me
“I don’t need to debug because I read my code.”
Same man told me to “make your code read like a novel, not a medical essay.”
I can go back to my old macromrdia / Visual Basic files and figure out what I was thinking back in 1997...
The other side of this is, "don't let perfection be the enemy of good".
As a novice I've made great progress taking this to heart. Writing ANYTHING is better than staring at a blank screen waiting for divine inspiration that will command your hands to write perfect code the first time around. It not it doesn't work that way, it can't.
I've even gone as far as intentionally writing a module incorrectly because I can't think of the right way. At some point, maybe hundreds of lines in, that conception of the problem domain will hit and it will suddenly become clear what I am supposed to be doing.
But I never would have gotten there without willingness to do it wrong first.
THEN, on the occasion I come up with a well designed object, I'll import them into new projects. That's where I can appreciate "don't throw away old code", but that "old code" is the survivor among many many versions that were thrown away.
Don't reinvent the wheel, and yet nobody is driving around on stone carved tires.
As a novice I've made great progress taking this to heart. Writing ANYTHING is better than staring at a blank screen waiting for divine inspiration that will command your hands to write perfect code the first time around. It not it doesn't work that way, it can't.
I've even gone as far as intentionally writing a module incorrectly because I can't think of the right way. At some point, maybe hundreds of lines in, that conception of the problem domain will hit and it will suddenly become clear what I am supposed to be doing.
We recently fired a developer who could not get past this concept. They would spend days trying to understand the entire code base before writing a single line of code.
We couldn't get it into their head that putting up a pull request that doesn't work and may miss the mark entirely, is a good way to start a conversation. (Our environment requires all PRs be reviewed and merged by a 2nd developer.)
In the meantime, the less experienced junior has pushed out three or four PRs for different issues, had them reviewed by a more experienced developer. The junior/senior talk about what was wrong / misunderstood / unclear, the junior fixes it. Maybe it takes a few go-rounds if it's a tricky or new concept. But the junior is learning from their mistakes and gaining ground. After a few months to a year, the junior needs less hand-holding.
The other person? Hired as a senior and just never produced anything of value.
That is very motivating. There is an open source project I want to contribute to, and I think I am actually starting to understand it. At first it made no sense, but then I started thinking about how I would design the project from scratch and the next time I looked at the existing project it appeared it was designed much the way I imagined it should be.
I am at a loss for what part of the unwritten code I should grab onto and tackle, but I can tell that I am intimidated by the idea of submitting less than some massive amount of perfect code (it is am implied requirement in the README).
Separating those two things will let me take a step forward. I need to take my own advice. Thank you :l
because it’s obvious that it doesn’t have problems
More likely is that it does have problems, but doesn’t look like it because it hasn’t been exposed to the patchwork of edgecases that inevitably haven’t been accounted for yet. That is, the code could look deceptively simple.
I agree though, the tendency is to throw the old shit away and re-learn what’s actually necessary. I’ve done this many times and will in the future.
OOP requires you to understand the innate structure before you code but, in particular with alg dev with a quick turn around time, very often you don't really understand the structure until its way too late at which point you know that it will have to be restructured because the current system's mismatch with the innate structure makes weird spaghetti hack code that is simply unmaintainable or extendable.
The first time you build the application, you don't know what you are doing. The second time you build the application, you don't know half of what you did the first time.
I worked on a system like this at my last job. It was a two part (cr)application. There was an API client and server. Neither of them used off-the-shelf OAuth libraries, instead a non-standards-compliant OAuth server and client were hacked together whilst apparently high on bath salts. One of the more interesting quirks of this was that you couldn't make requests with nested maps.
The result of that would be that the value would be evaluated as Array(PHP array to string conversion). This would then cause the signature strings not to match which would eventually cause the API client (there was only one when this shit show was created) to display the very helpful debugging message of Error: (no data). Interestingly, sending 0 or empty string as a value would cause this too(I think http_build_query stripped them out).
That was one of many many horrific things in that app. We also had endpoints that were named things like getGroupOfUsersForAdministrationMenu or whatever. Some API endpoints would return an array of users objects with varying properties. Some would return an array of integers that would be looped over to recover the objects by the client, some would return a pipe delimited string. On error, some API endpoints would return a JSON object {"error": "User is not authorised to perform this action"} some would just return an empty string and some would return nothing and just expect you to figure it the fuck out from the HTTP status code. Similarly, it wasn't uncommon to get an API error object like that served up with the status code 200 OK. If you requested all records matching <criteria>, instead of 200 and an empty array, the API would return a string (not even in an object sometimes, just a raw string) with a message along the lines of "No users could not be found matching your search" (yes, really!). This cheerful message would then be served up with a 404 status code which would be detected by the client.
Basically, the API reeked of something that was developed in parity with that one client and only that client.
Changing anything anywhere could have unpredictable disastrous consequences. Changing something as benign as the ordering of a list of records from an API controller could potentially cause a huge production failure preventing people from logging in (all with the helpful error message of Error: (no data)..or sometimes just an empty string which to me always seemed like the PHP interpreter saying "GL;HF".
Myself and a colleague inherited this horrific Rube Goldberg machine of a web app from the original dev who was off long-term sick after an accident. Despite my constant warnings of how bad things were, my warnings were ignored until we went live and replaced our clunky-but-working system with the new shiny-but-shitty system. We were expected to continue to just add features, add features and add features onto this horrible doner kebab of an application.
-Developing any feature or fixing any bug was like playing russian roulette. You might be able to deploy the bugfix fine, but you may also completely obliterate production because you changing the format of the person's name was somehow depended on by the permissions system and now everyone is an admin. Every deployment shortened your odds like bullets in a revolver.
Catastrophic fuck-ups like this inevitably resulted in a management interview with myself and the other dev who was the PM.
This PM proceeded to throw me under the bus repeatedly until management thought I was incompetent.
I used to regularly go home so angry that my blood pressure was so high that I was having nose bleeds whilst driving home
I'm a seasoned software engineer. Most the code I write is so freakin maintainable it is ridiculous. Clean code.. external run shell script, easy to read Dockerfile, clear setup and maintenance instruction in a README, automation deployment via Jenkinsfile.. and so much more. Any engineer that comes on board can look at my git repos and immediately be productive because they have containers to stand up their env, run scripts to turnkey everything, and clean code that helps understand the core source as well as the deployment and environment.
I almost never see anything like the effort I put into my repos.. it seems most dev teams are told to build something fast, not build something right. Then managers and C-levels wonder and get frustrated when the new team of developers want to nuke everything and start afresh.
Most software engineers are not in love with their work. They do it because it pays well and they get to go home at the end if the day and they don't care about the garbage job they've been doing.
First you make an implementation to learn about the problem space.
Second, you make an implementation to understand the best programming patterns to use.
Third try is done using that understanding.
mywan · 1 points · Posted at 16:21:31 on April 26, 2018 · (Permalink)
I only program for personal use and I always throw away the original program intended for a particular functional purpose. Often before ever even finishing the program. As I'm developing the various functional parts I tend to throw those functional parts together in an ad hocish manner. But once I have the functional parts working together I can better plan the overall program flow and think about improvement in the code explicitly intended to improve overall operability. Something I couldn't plan originally not knowing how the functional parts were going to be implemented.
What you say makes sense but you kind of say that everyone writes shitty code and you can only get good code by throwing old code away and writing from scratch. How about you read the good old Joel on technology blog post and refactor your post.
At the same time, if the decision to rewrite software is being made by the same people or the same type of process that led to the decision to rewrite it, then you're probably not better off rewriting it. Certain presumptions rest on the notion that the second time around will be better just because we "know" more. Those presumptions are impossible to quantify and risky to rely on.
In my mind, only if something significant has changed--better talent, different technology, better process--should you undertake the rewrite of a working system. Otherwise, best case scenario, you'll end up where you are now once again very soon.
I think the issue is not that old code doesn't work; rather, that the requirements change, and now you're struggling to adapt an old and possibly flawed system to do more and more things it wasn't designed for.
As someone who has only just started learning programming, I can already see this happening even with the really basic beginner code I am writing.
With my first couple of assignments I will plan it out, and have a go at coding the algorithm. If it doesn't quite work as intended, it takes longer to fix what's there then start again
m50d · 1 points · Posted at 09:52:09 on April 27, 2018 · (Permalink)
“The discard and redesign may be done in one lump, or it may be done piece-by-piece. But all large-system experience shows that it will be done.”
This is the missing link that reconciles these two positions. I believe Brooks explicitly stepped away from the "throw away" phrasing in later years, as it became apparent that continuous improvements to a working prototype/MVP are a more effective way to reach a good design than restarting from scratch.
I understand where you're coming from. And going from version 1 to version 2 means that you need to completely reimplement some things.
But here's the trick: you don't throw away the old product. You keep it, you maintain it, and maybe you even backport some features while the new one is in development. You never forget completely about the old code base.
And the actual test of time is not represented by your test suite, it's represented by your customers. Having good feedback and error reporting systems in place is a must for large scale software.
The idea that new code is better than old is patently absurd. Old code has been used. It has been tested. Lots of bugs have been found, and they’ve been fixed. There’s nothing wrong with it.
If you tried to apply the same reasoning to the human body, you'd be patently wrong. An older body (not of code) will be stronger than a younger one... but only to a point. On average, the body is strongest when you're in your mid to late twenties, and after that, it starts a gradual decline to the point that even a young child often has more ability than someone elderly.
Entropy will always win in the end. The young (both people and codebases) are those who have been affected by it the least.
It depends. I've been on many projects where the initial project requirements were "Oh, it's easy, you just need to do A->B->C->D".
Then you hit testing, or worse production, and then all kinds of wackadoo requirements materialize. "Well yeah, Most of the time you do A->B, but in these 3 situations you go to C, then back to B, then to D for 2 of them and C for the 3rd one." "Oh yeah, this other situation requires you to go to E, then spin a D20 and decide to go to B or C or end it in F". <time passes with more of this going on> Oh yeah, we don't do the B->Q->M on 3rd Tuesdays anymore, now it is B->R->E on 2nd Thursdays...
Last year I finally was able to fix one of those that had been going on for 10 years because I refused to directly translate the logic between languages during an upgrade.
This is a reality of software though; business requirements change all the time, and it WILL cause inconsistencies in the code. Its just impossible to account for anything that may change. The best you can do is design stuff to be as modular as possible (but within reason); write clean, well formatted code; and comment thoroughly.
None of that "I write self documenting code" bullshit I hear people say. No you don't. You think you do, but you don't. Write some comments.
My general practice for commenting is to go ham when it's business logic but hold of when it's very simple utilities. Generally it's only warranted when the code is complex.
Sure, requirements change. In this case it was a customer who didn’t know what they needed, a sales guy who wanted a sale, and management just wanted revenue while I ended up with it 3rd hand with zero docs.
the initial project requirements were "Oh, it's easy, you just need to do A->B->C->D".
"Well yeah, Most of the time you do A->B, but in these 3 situations you go to C, then back to B, then to D for 2 of them and C for the 3rd one." "Oh yeah, this other situation requires you to go to E, then spin a D20 and decide to go to B or C or end it in F". <time passes with more of this going on> Oh yeah, we don't do the B->Q->M on 3rd Tuesdays anymore, now it is B->R->E on 2nd Thursdays...
That's what happened when I designed the menu for my game.
While he makes some valid points, sometimes the codebase is just bad.
A tangled mess of rushed spaghetti code full of "TODO" and "FIXME",
and lots of temporary hacks.
At that point starting from scratch can be the right decision, sometimes.
ElGuaco · 155 points · Posted at 15:34:07 on April 26, 2018 · (Permalink)
People who are skeptical of this have probably never worked with a truly terrible code base. I think Joel is right about this in most cases, but there are always those cases that prove exception instead of the rule.
I once dealt with a codebase put together in ad hoc fashion by researchers who had no idea how to code properly and it was the very definition of tightly couple spaghetti code. Every time we needed to add a new feature it took weeks or even months to do it because it took so long to figure out how to shoe-horn in the new functionality without breaking everything else.
Finally, we got permission to prototype a version 2.0 that used good OOP, dependency injection, and unit testing and we modernized using RESTful services instead of SOAP. We had a working version in a few weeks(!) and fully replaced the old version within a few months while adding new features that had been on the wish list for years. This was no simple app, but a series of applications and web services and a large database.
Sometimes, you just have to acknowledge the fact that existing software is just bad and time spent fixing it is better spent on a replacement.
People who are skeptical of this have probably never worked with a truly terrible code base
I had a job where there were a dozen+ 30,000 line long classes. Not files, classes. There was a Globals file with ~2,400 variables in it. Every class basically stored its own copy of the system state. Previous developers would copy paste entire functions and change 1-2 lines instead of adding an "if" or parameter to add/change functionality. Every parameter (and global) was "Object" or "Arraylist" - nothing strongly typed, everything used late-binding. This was all in C#, so its not due to some cryptic language requirements.
Needless to say it nearly impossible to fix a bug without breaking something else. Over time most of it was simply tossed and rewritten because rewriting large chunks of the program was easier than changing a few lines.
ElGuaco · 14 points · Posted at 17:33:17 on April 26, 2018 · (Permalink)
At my current job, there is a core class that does a huge chunk of processing. The main method is over 10,000 lines long and has dozens of GOTOs. In C# with no unit tests. Several attempts have been made to refactor this class and all have failed.
Yeah, you need to figure out some way to break that monstrosity down and start creating tests for behavior. Even chipping away at it in small pieces can work (starting with the innermost loop / block).
That sounds like attempts to rewrite "hardware gospel" also known as the "magic sauce from the designers that make everything work". Never change "hardware gospel". Every time someone does, shit breaks bad. It's the only type of code in the Linux kernel that is allowed to break their strict coding guidelines because sometimes, they have to break the guidelines to make it work.
One PCIe device that I worked on needs data written to a certain location starting on a 3 and 3/4ths byte boundary without \a write of the lower 3 and 3/4ths byte. Why? I don't really know. It's some bug in some third-party IP Core in my design. So I had to write hardware gospel for the software team to force the Linux kernel to send a malformed TLP capable of writing starting at that offset.
I've worked in a codebase that had foo.h, foo.cpp, foo_2.cpp, foo_3.cpp and foo_4.cpp. I asked why there were four separate files for implementing the one class, and I was told by the author of the code (and also the owner of the company) that the IDE can't handle that much code in a single file, so he just makes a new file every time the IDE stops working.
phySi0 · 1 points · Posted at 13:32:14 on May 10, 2018 · (Permalink)
Previous developers would copy paste entire functions and change 1-2 lines instead of adding an "if" or parameter to add/change functionality.
Whilst duplication like that is hardly desirable, your proposed solution is not a great one.
Honestly, my VEX robot has 12k lines and I didn't even consider it that long. I'm really not trying to be
r/iamverysmart but it's been a year long process, and that's only part time, I'm willing to awnser questions. It's written in robotc, so I'm not sure how that translates.
If a project will only ever have 1 developer working in it, it does not matter that much. You wrote the code, thus (hopefully) you understand it. I am guessing all 12,000 lines are not in one giant file/function as well.
When you have a team of 10+ people working on the same codebase, standards become more necessary.
The codebase I was referring to was a safety critical (humans could die if things go wrong) application with ~450,000 lines of code. I don’t know how they passed certification in the first place with their garbage code.
Well, that's where your wrong buckaroo it is one file, mostly because the development software is a little sketchy on including files sometimes. And yeah, I know my robot is a little different and easier to manage, but I just wanted to say 12k lines isn't that much.
Personally, because I have so much of a codebase built up it's hard to transfer over to pros, and it's just what I'm used to. Plus speaker functions :)
I'll share some quick stats on the code base I currently work on...we're currently trying to rewrite it from scratch because it really is bad.
1) Most things are classic ASP / VBScript. A few years ago I got permission to upgrade some pages to WebForms
2) They never said no to any customer request no matter how inane. If a customer wanted some text label to be red there would be a switch case based on the account code to implement this functionality. When customers left these dead code paths were never cleaned up. This has led to honest to god switch cases thousands of lines long in some places to simply display a different image with different dimensions based on whatever customer is logged in.
3) Database never had any sort of design, giant tables with columns like col1, col2, col3, all the way up to 60. Terms like "One-to-many" were completely foreign to the original team. I don't think there are ANY foreign keys.
4) Every file was in the root directory except for the few things they opted to make into "libraries", and the naming scheme was some arcane thing involving roman numerals that no one understood. If it had any purpose the meaning has been long lost.
5) Custom encryption that was basically some XOR magic. Thankfully this has been replaced.
6) No classes or complex types (lists, dictionaries). All arrays are basically magic...you end up with things like:
etc., very simple example - it gets much worse once they start doing any arithmetic with the indexes. Oh, and they also decided to have the indexes start at 1 even though VBScript actually has 0 based indexing. Due to the hardcoded nature of the arrays adding anything is a pain and heaven forbid you want to remove something in the middle.
7) Type confusion everywhere. Cstr/Clng/Cbl on everything - even if you're pretty sure it's an integer. This is because you can't actually be sure it's an integer.
8) There are background 'processors' that handle tasks that would take too long to run in a webpage - okay fine. But they're ASP pages that run in fucking IE. Yes, the background server processing stuff has a dependency on INTERNET EXPLORER. They do log to the screen but it's hardly useful because the page refreshes every 5-30 seconds.
I could go on, and on, and on but I'll just leave it...I couldn't design a worse system if I was trying to do so. It's beyond bonkers.
lol that's gonna happen...have to hold out a few more months to get things in order but yeah they'd need easily 10+ more staff in various roles to get anything real done.
pdp10 · 4 points · Posted at 23:33:16 on April 27, 2018 · (Permalink)
This has led to honest to god switch cases thousands of lines long in some places to simply display a different image with different dimensions based on whatever customer is logged in.
Ah, the surprise "white label" requirement. That one can be rough.
I used to work with engineers who were fond of one letter or two letter variable names. And no comments. And couldn't understand why people thought their code was shit.
Oh, researchers. They are smart, stubborn and don't really care about programming. I think the worst codebases I've seen were produced by them.
BaPef · 5 points · Posted at 19:57:44 on April 26, 2018 · (Permalink)
I worked on a financial system that was built by an accountant with no development experience. It processed $600k a month and only during an audit did they realize it wasn't saving the signed loan agreements but rather regenerating it every time someone viewed it, for 14 years this happened and then when investors wanted all the contracts to review they requested we back generate all the signed contracts which is technically fraudulent.
So much this. There is absolutely a point where code should be thrown out.
Sadly my boss sides with Joel. I once had to estimate a project and it would have been absolutely easier to rewrite (literally half the time), but the boss told the Netscape story and I was told to deal with it.
[deleted] · 1 points · Posted at 09:07:26 on April 27, 2018 · (Permalink)
Jesus christ that sounds like some hellhole any junior developer would press the resign button so quickly.
The solution to the TODO problem is to replace them all with task numbers from your bug tracking software. That way you can explain what exactly needs to be done and it actually gets added to the priority list.
And then you have managers who count productivity and success by the number of open tickets and will try to close as much as possible of these tickets to look good
ccb621 · 11 points · Posted at 14:30:00 on April 26, 2018 · (Permalink)
Creating tasks definitely helps you account for the problems, but it’s not a guarantee that said tasks get prioritized. Many teams tend to be more product-oriented, and focused on delivering new functionality, so small fixes don’t get prioritized.
A priority of "just after hell thaws" is still a priority.
Alternately, when you see the task number in some code you are changing anyways, you can use that as a justification to make both changes at the same time.
[deleted] · 52 points · Posted at 14:29:55 on April 26, 2018 · (Permalink)
I feel that a superior option is to just delete the comments and forget about them.
If they describe really important actual todos, then they're already in the tracking software.
The advantage of keeping them in the comments is when you go to modify or refactor that section of code, you will take the ticket into account. Perhaps that ticket is about technical debt which you can easily do along with your intended change.
Additionally, if a bit of code has a bug attached or a FIXME, or XXX, when you're debugging a problem, or you just change that section of the code, and you come across the ticket link you will be informed of this critical information. Instead of figuiring out the problem all over again afresh.
So when it is time to fix that ticket, how do you know where in the code to make the change?
Originally my suggestion was just to get TODO's under control. But now I actively sprinkle task numbers in the code as bookmarks for what needs to be changed during new feature development.
kons_t · 2 points · Posted at 17:33:52 on April 26, 2018 · (Permalink)
When you want to fix a TODO, you grep the code for the bug number.
More importantly other than a few exceptions comments belong to commit messages. They mark not just a code location but a time and piece of work they were done for. Any decent scm gives you the blame tool through you can see the info tied to a line of code.
IDK if this is a default feature, but one of my coworkers convinced VSTS to search an entire legacy codebase for "TODO" and similar and create issues for each occurrence (there was no issue tracker before we got there). I thought that was pretty clever.
m50d · 31 points · Posted at 14:31:52 on April 26, 2018 · (Permalink)
I've found that even then, it's better to rewrite the codebases a bit at a time, and keep it functional the whole time. (The same principle applies all the way down: whenever I think "I'll just refactor everything in one go, it'll be quicker that way" and go into a 2-day dive I end up regretting it, it's better to make a series of 10-minute changes and rebuild and test each time, even if that means I end up doing multiple passes over the same code).
totes agree, I take the approach of building the replacement code in parallel and then cutting over the tests (if any) and functionality.
I think a lot of software rot would be helped by regular change management practices, and not like change control for releases, but looking a the dumpster fire of a code base and then deciding on how to get from point a to z in a structured way with no downtime.
ops people are better at this in some regard.
m50d · 6 points · Posted at 16:11:36 on April 26, 2018 · (Permalink)
totes agree, I take the approach of building the replacement code in parallel and then cutting over the tests (if any) and functionality.
That's not what I'm advocating at all. I find it much better to improve the existing code in-place.
I think a lot of software rot would be helped by regular change management practices, and not like change control for releases, but looking a the dumpster fire of a code base and then deciding on how to get from point a to z in a structured way with no downtime.
I find that all you need is the freedom to make small improvements every time you work on a code area. Point z is rarely where you actually want to go - by the time you get to point m you'll have a much better idea - so making a structured plan ahead of time is often actively harmful.
Yes yes and you think "Oh, I could do this way better!" Then you start writing it and you make all the same mistakes they did originally and the bug reports and feature requests start rolling in. Then before you know it, your code is a tangled mess of TODOs and FIXMEs.
Back in the '90's, I worked with a company that had licensed the AT&T UNIX source. A coworker was poking around in the vi source code and found a comment from 1970 complaining that the original programmer didn't like some bit of terminal handling that was going on, and he'd made a TODO to fix it one of these days.
Or you build a prototype that ends up full of TODOs and FIXMEs, and then you build a second rewrite, piece by piece, carefully documenting and testing each part as it’s added (knowing the real requirements this time, constantly checking with the prototype), and you end up with a version where there are no bugs left, the code is clean and tested. And with more features, and it’s much more stable.
At least for 20kLOC to 50kLOC, rewrites are useful and helpful. Maybe beyond the 50kLOC, 100kLOC or 1MLOC limit that changes. Also, during the rewrite you absolutely need to provide at least bug fixes for the old version.
Man, I wish I could do this at work. Instead, marketing has sold another year long project on a six month budget, and signed off another tragically bare “scope” without any developer input. Cue many months of trying to simultaneously build a system and decipher the actual requirements.
We have so many projects that are in upsetting states of disrepair and several with behaviour that is downright illegal once GDPR kicks in next month. But the boss knows the onus is on the client and not the contractor, and so nothing gets done unless someone else is footing the bill.
Yeah I can only do it because this project is more "fun" than work for me, and I don't have to pay my bills with it (although the Patreon and other donations certainly help)
The concept that maintenance involves iterative refactors/rewrites to keep the code base sustainable is lost on too many developers.
It's also useful regardless of the size of the code, as long as all changes are thoroughly tested/documented.
paolog · 13 points · Posted at 16:01:34 on April 26, 2018 · (Permalink)
Psst, TDD. Not very useful if you are maintaining a heap of someone else's crap and you don't even know what the required behaviour is supposed to be, but you have to start somewhere with your testing.
pdp10 · 1 points · Posted at 23:45:54 on April 27, 2018 · (Permalink)
Back in the '90's, I worked with a company that had licensed the AT&T UNIX source. A coworker was poking around in the vi source code and found a comment from 1970 complaining that the original programmer didn't like some bit of terminal handling that was going on, and he'd made a TODO to fix it one of these days.
Awesome apocrypha. But it must have been a different program or a different year.
Full-screen editors weren't used until glass TTYs became cost-effective, right around 1974. vi wasn't released publicly until 1978, but it was developed at Berkeley and I'm not sure when it might have gotten into the AT&T codebase. But C wasn't even developed until 1972 or 1973, and all 1970 "Unix" source, such as it was, was in assembly.
197ish, I suppose. My memory's not quite photographic, and that was 199ish.
phySi0 · 1 points · Posted at 13:26:12 on May 10, 2018 · (Permalink)
Yes yes and you think "Oh, I could do this way better!" Then you start writing it and you make all the same mistakes they did originally
A lot of things are just being taken as a given in this discussion. Who says you'll make all the same mistakes?
Skill differentials exist.
Philosophical differences exist, e.g. NeoVim's deemphasisation of backward compatibility with really old, barely used systems has allowed it to drastically improve Vim's codebase.
Time constraints can shift.
My axiom is that objectively bad code exists, not that a rewrite will always make the same mistakes. I think the first statement is what's self-evidently true, not the second, so I start from that. Sometimes, code is just bad for whatever reason, and a rewrite will not make the same mistakes.
Yeah, it's more of an "on average" thing. You very frequently hear "This code sucks and has to be rewritten!" from programmers, especially junior ones. Junior ones who haven't seen the requirements. Assuming there are actually documented requirements. But most of the time when you hear that phrase, it's coming from someone who hasn't seen the requirements and is severely underestimating the time and scope required for a rewrite. Very frequently, they've also been on your team less than a month.
I'm not saying a rewrite is never justified, but in many of the cases you can just refactor toward higher quality and it'll be a lot safer for the customers who are using your code.
Also, using completely the wrong tool for the task, lack of unit tests for complex stuff etc.
Tools and techniques change, so it is possible that a codeset has "rusted" in the sense that it spent a lot of time and effort on something that a modern library or framework makes easy.
However regarding unit tests...I have noticed a bizarrely high correlation between terrible code and loads and loads of unit tests. Some of the best code I've come across has nary a test at all.
[deleted] · 4 points · Posted at 14:30:37 on April 26, 2018 · (Permalink)
That's a trick question! You can only tell after taking the time.
How easy is the code to get running? Seriously. If I can get it to say "hello world" in short order, or run a simple test case in idiot-proof fashion, then it may just take time to understand.
But if even following the "setup" or "introduction" instructions fails, the code is bad & needs serious work.
dablya · 1 points · Posted at 19:45:30 on April 26, 2018 · (Permalink)
If you have to ask...
Even if you don't, the code needs to be understood before it can be judged.
It rarely hurts to take a sympathetic approach to someone else's code.
pdp10 · 1 points · Posted at 00:08:51 on April 28, 2018 · (Permalink)
Indicators:
High degree of code duplication. There are tools to find this, but it needs to parse into an AST, so I guess there are no language-agnostic tools. Maybe the LSP can be leveraged on this.
Nearly zero comments. Possibly indicates the programmers aren't confident they know what's going on.
Pro forma comments, like templates on every code block, that convey very little.
Lack of atomic commits into version control.
Non-idiomatic use of the programming language.
[deleted] · 23 points · Posted at 14:40:53 on April 26, 2018 · (Permalink)
And you think the new code is better? I guarantee you that there will come a future developer who makes the same statements about the new code. I realized this also that every code just becomes bad by lying around. So I asked around my fellow developers if they ever happened to see existing code which they considered good and didn't feel the urge to change anything. None every seen such a thing. So this is no way representative for anything, so tell me about your experience. Do you know such legacy code, which you would consider nice?
Edit: Oh now I opened the actual article. It's that one from APRIL 6, 2000. Yes 18 years ago the world was really a bit more messy than today.
[deleted] · 12 points · Posted at 14:28:02 on April 26, 2018 · (Permalink)
Very rarely. They did in fact have their reasons to make it like that, apparently the problem isn't as easy as it looks, and they had time constraints. Chances are you're being overoptimistic about your own future work as well.
I mean, maybe management has since decided that a much simpler approach is OK, or maybe you really are much better at programming than the people before you. But if not, it's just going to be a costly vanity exercise.
nikanjX · 22 points · Posted at 14:14:50 on April 26, 2018 · (Permalink)
You had 300 todos. You replaced them all with ”// TODO Implement entire app”.
Congratulations, you now have way less TODO entries.
In every single case, you should take that code, set it aside, and don't reinvent the wheel. If you are solving the same problem you will likely use some of that code again.
Or a software is fine for 2 or 3 years, but an alarming security update is needed, and no one knows the scripts and what will need to be updated. Or it was poorly built by the lowest bidder years ago for a paradigm the software doesn't even use anymore.
[deleted] · 1 points · Posted at 17:07:31 on April 26, 2018 · (Permalink)
My first internship was fixing legacy code that was written with minimal comments, variable names like x, m, n, counter, etc, and was a seemingly random mix of object-oriented and linear approaches. It literally put me off being a real developer and put me on a path to my current technical-but-not-writing-software gig.
Agreed. A big part of when to refactor is when the old code is inefficient, but works. If you're expecting to ramp up the sheer volume of the data you process, the old code might not be able to handle it in a reasonable fashion, hence a necessary rewrite.
There have been multiple cases where I started working on a company project and simply found that regardless of whether I thought it was "good" or "bad", it was severely unoptimized. Optimization isn't a necessity in most of these cases, but it's a nicety for both the end user who gets their info just slightly quicker and the server which gets to use far less resources and compute time over longer periods of time (on a one by one basis, sure, it's a millisecond, and negligible. But when considering thousands of calls, it matters quite a bit in regard to cost). If the code is bad, I refactor/rewrite it from the start. If it's decent (understandable by most of the team, doesn't cause any major issues), then I'll still refactor it, just opportunistically while adding / changing something at that level.
While he makes some valid points, sometimes the codebase is just bad.
Ever work on a codebase that began as a collection of unrelated "tools", then grew into a full blown application using at least three different UI frameworks?
I've long stopped asking. If I'm tasked to add a feature to component A, step 1 is clean up, step 2 is bug fixes, then step 3 is actually adding the feature.
How can I do it any other way? How would I know the difference between a new bug and an old bug if I don't first fix all of the old bugs?
In my case, I’m working with code that’s been around since the late 90’s. I’m just here like “This project is OBVIOUSLY gonna be around longer, just let me give some of it a makeover”, but of course that’s “not in the budget” or “not within the scope of the project”.
pdp10 · 2 points · Posted at 00:12:05 on April 28, 2018 · (Permalink)
You misheard. The plan is to replace it in three years. Probably they'll start looking in four years. Around the sixth year, they'll give up and go with either SAP or Oracle. You won't believe it when you hear it, but you'll instantly realize then that the old code wasn't so bad, actually. If only it had just gotten a little bit of maintenance once in a while.
I try to do this as I'm working on bug fixes or features in a certain area. Refactor this class, rewrite that method. Then document, write tests, and move on. Doubles development time, but I think saves time and money in the future.
It's the right thing to do, and I'm being paid for it. So what, the features don't land as fast and I have less time for Reddit. After a while I've taught my non-tech managers or customers to adopt to the speed of actually doing it right and with refactoring included.
The techy ones with my current employers know it as well as I do.
This is exactly what Joel is suggesting, and he is/was right for large majority of software projects. Some codebases are really shitty beyond recourse, sometimes an old technology foundation of software must be abandoned because it's not possible/viable to continue using it but in most cases rewrites are just new people's arrogance and lack of experience.
The three software smells and the approaches to deal with them are also spot on.
Which is why the modular approaches like microservices are a good idea. You can evolve and rewrie incrementally.
There is a great story by Uncle Bob about an attempt in a company he worked for (or consultet for, can't remember exactly) to rewrite a core app, that took a decade while the original was still being developed and was thus a moving target. By the end of it the new code was as smelly as the old one.
I feel like Netscape and Borland are very different from the software most of us are working today. Netscape is a desktop application with a massive code base. I'm currently working on web services and front end apps on the order of 10k LOC. I feel like rewriting Netscape is a much bigger effort (and more likely to go wrong) than rewriting these front end apps and web services.
The more things change, the more they stay the same.
boojit · 3 points · Posted at 01:35:03 on April 27, 2018 · (Permalink)
I really think there has been a fundamental shift though that came well after this article was written. I think it can largely be summed up as a move from monolithic applications to services-based (or microservices if you must) architectures. Amazon really needed to move from a monolithic web app to one that was built on a constellation of independent services with well-defined interfaces, when they did it some 10+ years ago. The effort requires a complete rewrite of their entire business, but not doing so would have been a fatal error. I am sure there were people at the time that would have argued the rewrite was a bad idea. Those people were wrong.
ivix · -5 points · Posted at 18:32:27 on April 26, 2018 · (Permalink)
A 10k loc web service is tiny. I've designed and built services that are closer to 500k and over 10 years old. They are exactly the same situation as the projects in the article.
Scybur · 17 points · Posted at 19:09:14 on April 26, 2018 · (Permalink)
500k loc web service.....what an absolutely shit design.
ivix · 15 points · Posted at 20:15:50 on April 26, 2018 · (Permalink)
Any mature codebase will be full of non-obvious code that is there to support what I like to refer to as invisible requirements.
Invisible requirements are requirements that do not appear in any design doc or user documentation, but the existing codebase has been written to support them. They are often the result of architectural or design decisions made during the original development; modifications made to workaround bugs or performance issues; well-known application features being used by customers in unexpected ways. Invisible requirements often fly underneath the automated tests, and nobody knows that they are there except maybe the crotchety old developer sitting in the corner (if he or she even still works for the company).
Any existing codebase is chock full of invisible requirements. Starting again from scratch means going through the pain of discovering them all over again (or finding completely new ones). This is not necessarily a bad thing. Sometimes a codebase is so bad that you need to start from scratch. This is usually the case when you can't even make minor code changes without tripping over some invisible requirements.
Invisible requirements are requirements that do not appear in any design doc or user documentation, but the existing codebase has been written to support them
An entirely valid point - and I expect to see comments explain WHY a certain piece of code exists, preferably with a link to the ticket!! It should also be in the commit message.
// JIRA-1234 PMs asked for this flag so <thisPerson> can do <xyz>
boolean someFlag;
Without such comments the result will (IMO) inevitably be a shitty codebase with truly invisible requirements and no hope of understanding them all.
Lucent · 74 points · Posted at 16:49:09 on April 26, 2018 · (Permalink)
While he may have a point, he picked the absolute worst possible example in history to illustrate it. Netscape 4 was garbage. You couldn't even resize the window without a complete reload. Hundreds of glitches in rendering. Getting absolutely destroyed by IE in every way. They made the best decision of their lives ditching that buggy codebase and beginning what would become Firefox, a revolutionary browser at the time. I'm almost certain trying to build Firefox off Navigator 4 would've been an absolute failure and disaster.
singham · 27 points · Posted at 18:22:04 on April 26, 2018 · (Permalink)
The article is 20 years old. I think there should be a date tag just like hackernews has so people commenting has proper context.
Holy shit, I remember this article. I thought it was stupid then, and two additional decades of programming experience has confirmed it.
Sometimes rewriting code is a bad idea. Sometimes a codebase is well and truly fucked, and it's holding you back. Most code is somewhere in the middle and needs to have time spent on it repaying technical debt. If you've got hacks upon hacks upon hacks, you're usually better off starting over.
Wouldn't it still be better to release Netscape 5.0 just to stay in the game, and incorporating Gecko in 6.0 without the rush? A bit like how Servo has been a separate project for several years and is now being merged into Firefox.
pdp10 · 2 points · Posted at 00:18:22 on April 28, 2018 · (Permalink)
As a freelancer who has taken on a lot of "fixer-upper" projects, I disagree a thousand percent. Most legacy code is garbage, and should be treated as such.
This article has an interesting way of ageing. When I read it the when it was first written I absolutely agreed with Joel, the rewritten version of netscape was absolutely atrocious.
However ten years later the decision to rewrite was completely vindicated with the success of firefox. Joels was then dead wrong. Mozilla would not have succeeded in making an IE killer tied to the very brittle code base of the original netscape browser.
Today the field is even more interesting, mozilla has a very interesting rewrite project with Servo. Now I think Joels main point stands, a lot of the instinct programmers have for wanting a rewrite is because it is much harder to read code than to write. As anecdata I do see a correlation with skill and how much maintaining a programmer has done
Servo/Quantum is actually a decent example of following Joel's advice. Mozilla didn't throw out the whole application at once, instead they are rewriting and replacing subsystems.
In the case of Firefox, it already had a decent modular design, and so the approach is a natural fit. I'm not sure the same can be said about Netscape; I have never seen any of its code, but the general opinion is that it was quite a mess. So a "Netscape/Quantum" approach might have been doomed to fail.
However ten years later the decision to rewrite was completely vindicated with the success of firefox. Joels was then dead wrong. Mozilla would not have succeeded in making an IE killer tied to the very brittle code base of the original netscape browser.
They offered it up for free for the first time. That is what made it. Rewrite be damned.
If they had offered up Netscape for free, IE wouldn't have had such a huge market share to begin with.
pdp10 · 1 points · Posted at 00:24:02 on April 28, 2018 · (Permalink)
Netscape was available gratis, although I can't remember the license terms -- it might have technically been for personal use. I was using it from 0.99 to 4.78, if that was the last one. Netscape was trying to make money on the server side, but never really got traction except where operators needed SSL or needed a server-side GUI.
Microsoft licensed Mosaic from Spyglass for royalties, then gave it away for free as IE, producing zero royalty obligations. There was a lawsuit about that one.
I remember it being a paid app and I got the quote from Wikipedia.
So maybe you should go and edit Wikipedia because obviously they have it wrong;)
Actually you have it wrong, but not worth arguing.
Maybe you had some student deal or something of the sort, but most people definitely had to pay for it.
pdp10 · 1 points · Posted at 01:13:39 on April 29, 2018 · (Permalink)
It was downloadable from Netscape's FTP site. The downloadable version was 40-bit export-grade encryption, instead of domestic 56-bit. I don't know precisely what the license was; it may have been "personal use", "non-commercial", or possibly even "non-expiring trial" for all I remember.
Here's one mention from a point in time: 1998-01-23. I definitely ran earlier versions for free on SunOS, Alpha (OSF/1, Digital Unix), MacOS Classic, and IRIX, and possibly others. The IRIX version may have shipped from SGI.
Reading may be harder than writing but that does not change whether the code in itself is bad.
I hate rewriting but very objectively the net result of the rewrite is often MUCH, much better than the prior version. This often happens because lateron it is more clear what the code should be doing; and whether it is doing it in a good way.
Sometimes a language design can also become better, and old expressions can be re-written in better ways too.
Very often the new code is also shit. Most large projects I've seen where the dev team decides to completely rewrite from scratch, they end up making a new giant codebase which is shit for completely different reasons, and it ends up taking way longer than anyone thought. Part of this also seems to stem from the fact that the rewrite team is rarely the exact same team that started the original project because too many years have gone by, so the rewrite is effectively the first time the current team has actually built the product. My own anecdotal evidence suggests rewriting pieces over time is almost always more successful than a full rewrite in one shot. Unless of course the codebase is fairly small.
they end up making a new giant codebase which is shit for completely different reasons
Speaking as a end user for a moment...
How many times have we all seen a piece of software get replaced by a new, better piece of software. Often a completely new product by a different company. But it's not any better, it's just crappy in different ways. Every once in a while, it truly is better, but not very often.
rjsr03 · 1 points · Posted at 16:09:09 on April 27, 2018 · (Permalink)
This reminds me of that saying of "sometimes there's no right, just different flavours of wrong" or something along those lines.
dsk · 38 points · Posted at 15:44:28 on April 26, 2018 · (Permalink)
Very often the new code is also shit.
Bingo. Typical dev arrogance is usually on the display when they think they can do a better job than their peers just a few years ago.
My own anecdotal evidence suggests rewriting pieces over time is almost always more successful than a full rewrite in one shot.
Mine too. I maintain an app I build with a team ten years ago. There are plenty of things I would do differently I started all over again, but we have hundreds of customers and thousands of users - it works. If code area inevitably starts getting flakey (and it will happen), we re-design it and rewrite it.
I think you're confusing "I can rewrite this because we know what the system is supposed to be now" with "I can rewrite this because I'm a better programmer than the original authors".
dsk · 2 points · Posted at 09:11:05 on April 27, 2018 · (Permalink)
What's the difference?
pdp10 · 1 points · Posted at 02:12:22 on April 28, 2018 · (Permalink)
I believe that ALL code is shit, new and old. The minute any line of code is written, they become a partial liability.
Most large projects I've seen where the dev team decides to completely rewrite from scratch, they end up making a new giant codebase which is shit for completely different reasons
I've been through many rewrites too. I know what you mean partially but I still think that rewrites have a net positive effect if they're done by people who really truly understand the problem, which usually means having struggled with the "old code" for a very long time.
[deleted] · 1 points · Posted at 15:25:15 on April 30, 2018 · (Permalink)
Are you me? I could have written this word for word
Merad · 48 points · Posted at 15:27:48 on April 26, 2018 · (Permalink)
It's very hard to overstate just how much shit code is out there, especially when you're talking about non-tech companies that don't put a high priority on software (aka most of the world). I'm not just talking about "I don't like this code," "this code isn't clean," or anything of the sort; I mean true steaming piles of shit. Here's a great example. At my last job our team inherited a 25+ year old application that was bad overall (to the point where we had to rewrite it), but one enhancement added in the late 2000s really stood out.
This feature involved connecting to a serial device using the .NET SerialPort class and reading measurements sent ~20 times per second. The data format was basically STX1 NN 00\n where STX is the actual "start of text" character (0x02), NN is 1-6 decimal digits, and the spacing is variable but the length of each line is fixed (16 characters IIRC). In order to parse this, the original developers had come up with a 200+ LOC monstrosity that had three nested infinite loops interacting with 3-4 global variables, including a timer (???)... in addition to about 4 old commented out versions of the parsing code with the same basic layout. I never did manage to figure out how the hell that old code worked, but my replacement amounted to about 20 LOC total.
Reminds me of the worst piece of code I have ever seen on finding a maximum. Back in college I took a difficult operating systems course in which you are partnered with somebody for the year. My partner happened to be pretty bad at coding.
One of the assignments, each of which takes about 100 hours over 2 weeks, was basically creating threading/processes, with a separate far easier segment for creating a scheduler. I told my partner I basically will do all of it, but I will pass to some function "grab next prioritized thread" for the scheduler and he just has to write the function on deciding which thread is next. He spent maybe 5 hours tops while I did the other 95% of the project, and I didn't bother reading what he had written for the code since it was working.
We got the project back docked for design decisions. I was baffled and spoke with my TA about it and asked why, and he pointed to the scheduler... Each thread was given a priority, and the highest priority thread was the one to be used next in the scheduler, so he had to write a function for "find the thread with highest priority".
The function he wrote... for finding a maximum...
for (i = UINT_MAX; i > 0; i--) {
thread = find_thread_with_priority(i);
if (thread != false)
return thread;
}
Or basically, start at maximum possible number -- does a thread exist with this priority? No? Okay, repeat with maximum minus one. No thread? repeat... Until you find a thread... I couldn't believe what I was reading
Merad · 6 points · Posted at 21:41:27 on April 26, 2018 · (Permalink)
I don't know what you're complaining about, that algorithm always finds the highest priority thread.
/s (should probably be /cry)
tehftw · 1 points · Posted at 06:29:10 on April 28, 2018 · (Permalink)
I mean, umm, if the number of threads at some point is greater than UINT_MAX... What the fuck were they thinking?!
Depends. Is old code shit because it’s bad? Or is old code shit because somebody else wrote it?
Many times this is used to replace code somebody else wrote and the new programmer doesn’t understand the new code and why it was designed that way. Then during the rewrite, you discover all the reasons why it was written this way. Reading code is its own skill and it’s under appreciated. It includes deciphering the original requires as implemented.
Then during the rewrite, you discover all the reasons why it was written this way.
And you find out that it's been on life support for years (while every user loathes using the library) because the guy that wrote the core functionality as a young engineer is now management and protecting their own legacy, even though that little piece of code has since gone through puberty, gained oodles of stapled-on submodules like pimples, and attained young adulthood in a haze of alcohol-fuelled bug workarounds and getting high on outdated code quality and compatibility standards. Might be time to take the manager aside and break it to him gently that Jr. needs an intervention and rehab via a massive re-write, and when it comes out the other side as a brand-new version, that manager can still say, "I remember that software back when it was v0.10, because that's my baby." and take credit, even though now the code is a likable, well-adjusted, mature application instead of a buggy, immature ne'er-do-well.
Or insert whatever tale(s) of woe you like, but that is the nature of technical debt. Never paying it off makes the debt bigger over time. Now ain't that interesting?
Eep1337 · 48 points · Posted at 14:38:18 on April 26, 2018 · (Permalink)
for you, but what about for the customers?
Is a rewrite a success if you miss 50% of the features?
And I don't mean rewriting some small 20,000 line app....I mean rewriting a 1,000,000+ line enterprise app.
A lot of consulting work is finding these mis-matches between staff and management. Sure we write code, but that's really a small part of what we're about. (Which pains me to say because I don't want to be a consultant, I just want to crank out boring but useful software.)
dsk · 27 points · Posted at 15:38:42 on April 26, 2018 · (Permalink)
And I don't mean rewriting some small 20,000 line app.
I think people clamoring for rewrites in this thread have tiny JS apps in mind. Yeah, I agree, in those cases - go nuts. Rewrite your Angular app in React because it's cool.
Rewriting a legacy enterprise application with hundreds of thousands or millions of lines of code will take years! In the meantime, there's a business that needs to run.
Eh, even this shouldn't scare you off. In a case like this you don't try a full rewrite at once, you tear off small pieces of functionality bit by bit.
dsk · 8 points · Posted at 16:40:06 on April 26, 2018 · (Permalink)
In a case like this you don't try a full rewrite at once, you tear off small pieces of functionality bit by bit
But nobody argues against that. That's the way you should do it. The entire debate rests on whether it is generally a good idea to do clean, total, group-up rewrites of large existing codebases.
That's partial reworking, also known as maintenance, typically regarded the polar opposite of throwing it away and rewriting from scratch.
Eep1337 · 10 points · Posted at 15:44:44 on April 26, 2018 · (Permalink)
Yeah. I notice this sentiment a LOT with junior engineers coming into my company (we do legacy enterprise, go figure)
It is a delicate thing to explain. To be a great engineer in a shop like this you have to be equal parts engineer and businessman.
These days I try to incorporate a bit more communication and general business knowledge in my training rather than just "go here to debug this"
I want to prepare these kids for whatever the world might throw at them, and from what I've seen so far, understanding the business (even at a shallow level) and being an effective communicator will get you that raise and that recognition. Those skills will translate anywhere.
ckwop · 6 points · Posted at 21:09:21 on April 26, 2018 · (Permalink)
The way I explain this to my staff is to just look through the history of the industry at even a superficial level and you'll know that large software projects are incredibly risky.
Many are never delivered. Most are late. Most don't finish with the intended scope.
If you re-write your main application, which has had year after year of hammering on it by developers it will be a large project and possibly the largest one ever undertaken in your business.
Large projects tend to fail more often than smaller ones. There's a reason for that. When we double scope, we do not double effort. Effort does not scale linearly, According to COCOMO, it scales between n1.05 and n1.2
These rewrites are usually far, far larger than any project previously attempted. It will take far more effort than anyone predicts and because it's so expensive it will probably be less capable than the system it replaces.
zuchuss · -3 points · Posted at 23:05:52 on April 26, 2018 · (Permalink)
Mhm interesting. I would just add though that unless your degree is ABET accredited then you need to put engineer in quotes.
For example, I'm sure you work with a lot of software "engineers."
[deleted] · 1 points · Posted at 23:41:49 on April 26, 2018 · (Permalink)
[deleted]
zuchuss · -2 points · Posted at 00:02:36 on April 27, 2018 · (Permalink)
Well you guys used to call yourselves programmers but I guess that title just didn't carry enough weight anymore and so it went to software developer and then of course the infamous "software engineer."
Don't get me wrong, there are truly real software "engineers" out there. People that work at a low level with a fundamental understanding of what goes into it and design things like operating systems, engineering software, etc.
Most however will never leave the safe space of Visual Studio.
Just because you don't "leave the safe space of visual studio" doesn't mean you aren't a software engineer. I'm no software engineer but I'm pretty sure that writing a million lines or more of code requires some form of engineering, at least.
zuchuss · -3 points · Posted at 05:03:46 on April 27, 2018 · (Permalink)
import numpy as np
certification = ["""print("im an engineer")""" for i in range(999999+1)]
That produces a million lines of code written to a file (space delimited). Clearly you don't understand even the most basic code but you felt qualified enough to drop your 2 cents. Found the IT guy.
That is writing the code, and the purpose of my earlier post is to simply expose the fallacy in your logic. Further arguing semantics makes you look quite the dunce.
using a strawman fallacy to expose a supposed fallacy? nice logic man, i want whatever it is you're smoking. go take a look at the linux source code, or any large system and tell me you don't need any software engineering skills for that.
i'm not sure what you're getting at. you wrote a program to write a program with a million LOC. That means you just wrote a single 3 line program, and the program wrote the code. Ignoring the fact that you can compress that code into a single for loop and thus invalidating your entire argument, you seem to be missing the point. whether it's because you're a troll or you're simply thick, i don't know.
ah, so you admit it's not a million lines! congrats on being wrong. you had no clue, have no clue, and will never have any clue of whatever you're saying because you're a fucking moron. I weep for the education system that failed you.
Lol you went back to ninja edit.. I mean "fix"... a post so you don't look like such an idiot... When we're the only ones who will probably ever see it. Dunno if I should laugh or cry because buddy, that's pathetic. This has ran its course.
ninja? boi u must be blind if you think that's a ninja edit. i literally told you i fixed it just now and you think that's a ninja edit? get some glasses
what happens if that massive codebase still needs a re-write, and its shitty architecture means it can't be modularized and re-written in pieces?
It's cute that companies pretend their 20+ year old code is "time tested" and "stable", that taking months or years to make changes is the "cost of doing business", and browbeat new hires trained in more modern, better tech into accepting that change is impossible and there's no fixing the codebase will allow that company to survive. Stagnation is only going to ask for trouble. Better to rewrite now and be able to run both systems against each other, than have to fire up an antique when the old system and its language is no longer supported by newer hardware.
dsk · 14 points · Posted at 17:12:34 on April 26, 2018 · (Permalink)
what happens if that massive codebase still needs a re-write
Then you do a rewrite. The point is that a rewrite is something that is done as an absolute last resort - when you've dismissed all other alternatives.
It's cute that companies pretend their 20+ year old code is "time tested" and "stable", that taking months or years to make changes is the "cost of doing business", and browbeat new hires trained in more modern, better tech into accepting that change is impossible and there's no fixing the codebase will allow that company to survive. Stagnation is only going to ask for trouble. Better to rewrite now and be able to run both systems against each other, than have to fire up an antique when the old system and its language is no longer supported by newer hardware.
I don't know what to say about that other than the fact it is an incredibly shallow and naive perspective. It's easy to make proclamations when you aren't actually running a business and needing to actually bring in revenue to pay your expenses.
Watched it, experienced it, my man. Perhaps it's not a practical point of view, but waste is waste. In this case, time, money, and effort in maintaining a stack that acted like the Leaning Tower of Pisa, and it's still a matter of time before the whole thing collapses and then no business is getting done.
But by all means, run up that technical debt and move on to greener pastures before you're stuck footing the bill on a long-overdue rewrite.
what happens if that massive codebase still needs a re-write, and its shitty architecture means it can't be modularized and re-written in pieces?
There's no such thing. Refactoring the code without changing functionality is always an option. The first half of my career was solely dedicated to taking bug balls of mud and iteratively cleaning them to the point where you could make decisions about replacing individual components.
One thing that confuses me is how a single package with millions of lines even exists. So many platforms have ways to nicely divide code so I would hope developers would use that. If they didn't then it probably means code quality is low as well. Maybe don't do a rewrite but maybe replace each feature one at a time. Or identify a smaller section of the product that can be rewritten.
Sometimes it's hard to separate features with bloat in general. The example in the article is Netscape, and in terms of web browsers I switched to Chrome because it was lighter and less bloated compared to Firefox which did have more features. With a redesign higher quality can trump quantity.
It's all the OTHER features you might miss. Accidental ones (the old "bug is a feature"), or features hidden in messy code.
At the end of the day, in a large enterprise application, having 100% feature documentation is not easy. When you rewrite, you risk messing with the end users work flow, even if you "fix" things that should have never happened in the first place.
Is a rewrite a success if you miss 50% of the features?
Google Docs has less than half of the features of Word, and Spotify has less than half the features of iTunes.
You rewrite when the business environment changes so that the features you thought were vital no longer are.
[deleted] · 2 points · Posted at 17:34:50 on April 26, 2018 · (Permalink)
A rewrite shouldn’t break anything. If you’re removing features with your rewrite, you’re doing it wrong (where do you work that this is ok?). All tests (automated or manual) should still pass.
The reason it doesn’t happen is because PMs don’t want to assign work that isn’t needed. If it ain’t broke...
Now, if people are having problems because of some code that’s a different issue.
Very often the old code IS shit. [...] I hate rewriting but very objectively the net result of the rewrite is often MUCH, much better than the prior version.
Completely agree.
Granted, my experience is limited to:
Code that's purely for internal use - no external customer
Written by engineers
10-100k LOC size
I feel like inevitably, the requirements or use of a tool or application will outgrow its initial scope. It's a question of when, or how well the initial architecture was designed for extension and maintenance.
Eventually, the cost of a ground-up rewrite outweighs the misery of an increasingly convoluted, difficult-to-maintain/develop codebase. I've only gone and done this a couple times, but it is so worth it in the long run. Better foundation that's 10x faster to develop with, easier for new people to jump in and contribute, etc etc.
I feel like inevitably, the requirements or use of a tool or application will outgrow its initial scope.
This. This is 1 of 2 essential reasons why re-writes are tempting in any codebase that lives long enough. (I still don't advise it though.)
It's a question of [...] how well the initial architecture was designed for extension and maintenance.
The trick here is that how "well" you designed the system for extension is based on how well you can predict future requirements changes. And predicting the future is notoriously hard. Example: following open/closed principle, etc. everywhere in a system that doesn't end up changing results in a codebase that is unnecessarily hard to read.
The trick here is that how "well" you designed the system for extension is based on how well you can predict future requirements changes.
Yup. For sure. Totally agree. "Getting it right" the first time around is difficult if not impossible. Compounded of course if there's a pressing time constraint and there's the desire/need to just get "something" together without really sitting down and thinking it out up front :)
10k lines is a micro-project. I would have no qualms about rewriting something that size. Even 100k lines is not too bad. When you get to the millions or tens of millions of lines, attempting a complete rewrite is doomed to failure. You are throwing away a huge amount of hard-earned domain knowledge by doing that. An incremental rewrite is the only way you can possibly succeed.
It's also important to remember that teams of devs get better over time - the code your buddy wrote two years ago may be vastly worse than the code you're writing now, but you might have done just as badly.
I hate rewriting but very objectively the net result of the rewrite is often MUCH, much better than the prior version.
This is what it sounds like to not yet have learned from one's mistakes: rewriting seeming always like a good idea. Even worse if that turns out to be true!
LukeLC · 11 points · Posted at 18:31:05 on April 26, 2018 · (Permalink)
As someone who threw out an entire codebase and spent the last two years rewriting it: no, I was not wrong. There's good (bad?) reasons it was difficult to read before: it was a mess. The new codebase is so well organized I can put it down for long stretches and get reacquainted with it easily.
The key here is whether you're scrapping an idea or just your execution of it. In my experience, my original ideas are often sound, and when I later ask why I thought of something so ridiculous, it usually turns out there's very good reasons for it. But execution can always be improved, and sometimes that requires low-level rewrites. Everything else is just iteration.
I mean, where I work the control software we use has been in continous development since the early 90s. Which makes changes which would take 5 minutes on new code take 4 hours instead.
There comes a point when the old code should be thrown out.
Back in 2013 I pushed my team to rewrite our codebase in RoR. Originally it was a 600k+ line PHP and JS app.
You are giving a gift of two or three years to your competitors, and believe me, that is a long time in software years.
It took us roughly 3 months to get stable.
It’s important to remember that when you start from scratch there is absolutely no reason to believe that you are going to do a better job than you did the first time.
We learned from our mistakes. I 100% stand by my decision. The increase in productivity was invaluable. The code base is now less than 30k lines. Don't haphazardly rewrite your entire codebase, but don't take this article too seriously either.
Edit: I realized I wasn't counting the templates in the RoR app while the templates in the PHP app were all included in my initial count. And in an effort to be fair, a more accurate total for the RoR app actually stands at 41k lines. While going back to investigate I also found that the PHP app had a 25 line license in almost every file, amounting to roughly 86k lines of license.
Its all subjective. There ARE codebases that have so much technical debt that you can't possibly fix it all without it being a re-write anyways. Then there are cases where a re-write is temping because things are not perfect, but in reality the code base is good enough to get the task done.
For the cases where a codebase really has to be re-written, I find it is almost always because one or both of these reasons:
Someone who wasn't experienced enough was in charge in the beginning, worked in isolation, and they set a foundation that was doomed to fail.
The project lacked any peer review and/or planning that would have prevented a problem from getting out of hand.
The second item is really important. Project leads a lot of times think they have to review code, but their own code does not need review. this is false. Noone is immune to making mistakes, and I firmly believe that every piece of code in a system should be reviewed by at least another person regardless of the seniority of the person writing it.
Except that's it's not AND it's not the reason most people want to throw out old code.
There are changes in technology, there's bad design and bad code out there and constantly applying bandaids instead of biting the bullet and starting fresh is a bad way of looking at things. I'm not saying throw out the code every time but there needs to be a line drawn at some point.
Case in point some of our in house software is in VB6; It uses controls that have no 64 bit version ocx because whoever made the controls stopped existing before 64 bit os and I'm not even sure we could get them working registered on windows 7 32 bit for that matter. This means we have to have a windows XP VM in our pool in order to make bug fixes or update features and hope to god nothing happens to corrupt that box and its backups.
It also means I can't install VB6 into a more recent version of windows to run debug in an environment that matches what one of my users has. Instead when I want to debug something I'm not experiencing on DEV I have to add a ton of Msgboxes that yell various profanities where I THINK the crash might be and see which profanity doesn't pop up. Had an instance where the user changed his region settings to french, and it Borked a CDATE() somewhere because it didn't know how to deal with the french version of the Month.
The programs talk to a set of access databases and has some of the most convoluted code I've ever seen. I hate that code with a passion, doesn't mean I can't read it, it's just retarded.
For instance whoever coded this originally made a Replace function that overwrites the built in Replace function with a significantly worse one that is prone to infinite loops, because why the fuck not?
Or how about the fact that every table is loaded into a "temporary" table before being read.
seriously...
Everywhere in the code there is a call to a function that drops tblTemp followed by a select * into tblTemp from whatever table they need at the time no joins or anything fancy like that and THEN the code does a select * from tbltemp where blahblahblabedyblah.
This software runs at over 60 locations across the country, I have to interrupt these people's workdays for 20-30 minutes to run fucking compact and repairs in access at 99.9% of these locations on a weekly basis because they run the risk of hitting the 2 gig database limit.
Not to mention every SQL command you have to write has to take into consideration the fact access is a "special needs" child and doesn't like to follow normal conventions. It's the Internet Explorer of databases.
There is stuff in there that has 100's of lines of buggy code doing things which I could do in 20.
Have I mentioned it's VB6 code yet? Yes I have. Know what that means? No Try/Catch. Error handling/logging is shoddy at best and non existent in most cases.
Here's the thing, I can read old code fine... the problem is that it reads like the fucking Twilight Series...
I understand your pain with Access. I help maintain an EOL software originally written in Access, that is being ported bit by bit into another tech stack. The things you have to do in Access to get it to behave is nuts.
A the very least, the majority of the tables are linked; internal tables are only used as temp tables. Even so though, it does not scale. Its something that is great for a small business with like 20 employees max, but if you ever want to grow, you will need a new tech stack.
Yep, I just did a full deployment of SQL Server 2014 (2016 is not compatible with windows 7) to all my users over the past month.
Took about a week to download, install and configure SQL Itself on all the computers and I was doing 4-5 machines at a time (Thank you Logmein.), had to fight a couple users because they kept stopping the download.
Then three weeks of setting up individual copies of the new SQL database, dropping in a linked tables version of the old db's, creating odbc connections and making sure everything loads.
Probably would have gone a bit faster but;
I'm the IT Swiss Army Knife (Net OPs, Tech Support, Coder, Office Support, New System builder, pretty sure I have a toast function you can access with a nipple or something.) so I can be stopped by random crap at any time.
Had to stop deployment occasionally to do some emergency code changes because certain things we do in the old apps and in the newer .Net apps we've added over time don't behave well with linked tables. Like Sub queries, anything with a sub query will time out if you go through a linked table. Linked tables also don't like it if you try to do a read of records that are not committed.
At least for the .Net stuff I was able to just change connection strings, which provider to use and then de-accessify the SQL queries. The VB6 stuff required either a full workaround or getting rid of transaction/commit/rollback functionality.
The trick now is to finally get the boss to OK a rebuild but convincing him to keep the new versions as Forms Apps, not Web Apps which he seems to have a huge boner for right now... because that is a whole other nightmare and I will not do code fixes for web apps.
I am way underpaid for the amount of bullshit I have to deal with '-_- but I'm pretty sure no other company would tolerate my issues at this point.
Why would you install SQL server on every machine? The idea is to have a centralized server that everyone connects to via an ODBC connection. How would you keep the data synchronized otherwise? Maybe I misunderstood you.
You absolutely can use sub-queries in linked tables, you just may need to bypass Jet if you want to get performance. You can do this by bypassing ODBC altogether within the VBA for certain queries, and running native T-SQL instead. However, subqueries can be slow in general. You can get a similar effect using CROSS APPLY and OUTER APPLY instead, and it generates a much better execution plan. For example:
SELECT a.id,
b.total
FROM a
OUTER APPLY (
SELECT SUM(amount) AS total
FROM expenses
WHERE expenses.a_id = a.id
) b
This is faster than using an equivalent subquery (of course there are other ways to write this trivial example, but just trying to demonstrate the syntax).
In fact, I suggest bypassing ODBC altogether unless you need to also interface with local tables within an Access DB, or you need to use it as a form recordsource.
Why would you install SQL server on every machine?
Because the machines are located across the country and they are self contained entities(Independently operated stores to be precise, we just provide the branding, the tools they need to do the job, the access to our supplier base and the support.) They need to be able to do things regardless of whether or not their internet is down, our internet is down or the universe explodes.
There is no point for instance in forcing the user to go out to the internet, to OUR servers and back to.
Lookup or modify the price of an item on the shelf then print a new shelf label.(Which will also automagically update the cash registers.)
Do the receiving of a pallet that just got dropped off.
Make an order to restock the shelves.
Check if the item in the empty peg/shelf is worth re-ordering of if they should just try a new thing.
Bought bunch of stuff from an unauthorized vendor? Authorized Vendor sent a substitute instead of the item you ordered and it's not in the system so it doesn't scan? Don't need to call ME or the Moichansing department, takes literally a minute to add it in.
All stuff they can do quickly and efficiently at any time with their handheld scanners (which is running good, clean .net code.) because they are working locally.
This is one of the main reasons I am against going Web App as well. Centralized over the web gives two hard failure points for EVERYTHING(Net is down at A or B) and a soft failure point as well(Net is slow somewhere down the pipe).
Net goes down? Only thing they can't do is hit the send button on new Orders to Suppliers but they can make the Orders just fine because everything except that Send button is done within the confines of the store itself.
Now Centralize all that or build a web app. Net goes down? Huge chunk of the stores operations just went belly up. Net's slow? Every single thing they want to do now takes that much extra time.
As far a sync goes we already had a set of Polling software's (one up, one down) that would sync our data with theirs on a regular basis, that is the .Net software I changed to use Native SQL connection.
You absolutely can use sub-queries in linked tables, you just may need to bypass Jet if you want to get performance. You can do this by bypassing ODBC altogether within the VBA for certain queries, and running native T-SQL instead.
Never said you can't, I said it doesn't behave well with it which is why where I could I nixed the ODBC/Linked Tables and wen't native SQL instead.
I still have some work cut out for me but by the time I am done the only thing that will use the old databases will be the two VB6 programs.
Ahh I get it, its an end user product. I thought it was a single business with a lot of locations. I'm double surprised that you are stuck with VB then.
I agree with you that a web app is a bad idea; it just opens up security issues. Remind your boss that the Equifax hack happened through a web based API.
ericgj · 1 points · Posted at 18:02:45 on April 26, 2018 · (Permalink)
Oh man I thought I had it bad maintaining old VBA/Access applications. I started to write "have you tried..," and "what about...?" but it sounds like you crossed that line of "rewrite or be tortured" about a decade ago :) My condolences.... hope you find a way out!
access is a "special needs" child and doesn't like to follow normal conventions
ROTFL I feel so guilty from finding this hilarious but I do!
Also, "2 gig database limit," that can't be normal? I apologize in advance I'm super new to programming.
Nope, you hit 2 gigs and everything stops working until you either compact the database (if you can) or split it.
Most of the time a compact is fine because the 2gb is mostly bloat due to the fact access doesn't actually clean up after itself Delete commands, drop commands, indexing, basically everything you throw at it gets stored inside the db in a set of hidden tables and it's only removed when you compact.
The reasoning behind it is that it was built as a 32bit application for 32 bit OS which had a 2gb ram limit on applications
as for the "special needs" comment
True; Rest of the world: 1 or 'True', Microsoft Access: -1 or True
Dates Rest of the world: 'A Date', Microsoft Access: #A Date#
Getting a date Rest of the world: GetDate(), Microsoft Access: Sends a Dick Pic... err I mean Now()
Where Clause Rest of the world: Where A = B And (C <> D or C < E), Microsoft Access: Where (((((((((((((A =B))()() and )))((C <> D) or ¿ C < E)))))))&$@ I may be slightly exaggerating the level of retardation but go play with the query builder in access on day and see how many () it adds to fairly straightforward where clauses.
I mean you're talking about a programming language named around a speech impediment... Makes sense to me that it would be annoying to put out.
wwqlcw · 6 points · Posted at 15:17:36 on April 26, 2018 · (Permalink)
I think it would be very interesting to see how developers' attitudes about this "rewrite vs. fix it" issue corresponded with years of experience.
I'd guess that new developers would lean toward "fix it," developers with a few years of experience would turn toward "rewrite." And the grizzled vets would be back at "fix it."
Piecemeal refactoring isn't something most developers enjoy, but in contrast to a total rewrite, it can produce positive, tangible results very quickly. It can be fun. It is also, from a business standpoint, safe and cheap.
Fast, safe, cheap: choose any three. How often do you get an opportunity like that in engineering?
Something Spolsky doesn't mention here, but something I've noticed in my own projects: What you recognize as "cruft" in old code that someone else wrote often turns out to be, on much closer examination, "features." It's not until you examine it in the kind of detail required for a rewrite that you realize all the subtleties of the way Feature A and Feature B interact with each other. Your rewrite might be slightly cleaner than the original, but it's not going to be the sleek glistening monument to your own genius and discipline you imagined when you started, because the interaction between A and B just turns out to be complicated. Not complicated as a programming exercise, but actually complicated in the real world.
[deleted] · 6 points · Posted at 15:58:41 on April 26, 2018 · (Permalink)
My current project is the only time I've ever actually rewritten a codebase, and the only reason I even considered it was because the application is small and it was actively corrupting and exposing data. It's the only web application I've come across that would merge and corrupt data if two people interacted with it at the same time.
The reason I want to throw away old code is because when you first write a program, you aren't really sure what the best way to do things are. You might not even be quite sure what you want to do. Once you write the program, you have a much better idea of these things, and could rewrite the program in a much cleaner way.
Of course, your manager doesn't want to allocate time for that, because the first version works, doesn't it? So then a year goes by, and someone looks at your code, and wonders to themselves: 'what the fuck is this?'
Of course, your manager doesn't want to allocate time for that
Have always looked at this kind of refactoring as a kind of machine mantenance.
There is gradient of these none, very minimal, minimal, okayish, slight improvements done too, and quite a few improvements mantenance.
Example of very minimal is perhaps just rubbing the thing down with a cloth. Minimal making sure that it is lubricated, tensioned and such. Okayish is then on the order of regularly cleaning it out, inspecting and replacing worn out parts and such. Then there are improvements like replacing a faulty sensor type for a better one, adding belt tensioners springs or such. And at last a few examples of quite a few improvements is adding sensors and control board for something that had to be checked manually otherwise. That sort of thing.
Most managers do not see the value of going beyond minimal or okayish mantenance though.
[deleted] · 11 points · Posted at 15:29:50 on April 26, 2018 · (Permalink)
Yeah I feel like the general consensus here is that the title/article is ridiculous. You know a good code base when you read through it and similarly, you know a shit code base. The amount of technical debt that gets built up over months/years of maintaining bad code is incredible. And the amount of time wasted is too. I don’t know why programming is viewed as different from other fields; you wouldn’t write a report and submit your first draft. You write some ideas that get your point across, but it’s shit and not structured well, so you keep small parts and rewrite most of it. The only difference is that writing a code base takes longer and passes through different hands. But the goal should always be to write the best piece possible and improve where things can be improved, not persist trash
As someone who is not a programmer, I can’t imagine how frustrating (and rewarding) some of that coding may be. Props to all of you, and I appreciate what you all do for the world.
I’ll tell you why: those are bug fixes. One of them fixes that bug that Nancy had when she tried to install the thing on a computer that didn’t have Internet Explorer. Another one fixes that bug that occurs in low memory conditions. Another one fixes that bug that occurred when the file is on a floppy disk and the user yanks out the disk in the middle. That LoadLibrary call is ugly but it makes the code work on old versions of Windows 95.
Those aren't bug fixes. Those are workarounds. The system underneath the program has bugs, is unreliable, or has various quirks that make those workarounds necessary. But the bug certainly isn't fixed, merely sidestepped.
Oh I understand the incentives: if your program crashes because of a bug in the Windows runtime, it is your fault, not Microsoft's. If your game has glitches whenever it hits some bug in the graphics card driver, it is your fault, not Nvidia's. When customer see your program not working because their setup is broken, it is your fault for not foreseeing that, not theirs for not investigating. Basically any flaw that your program reveals is your fault, because the final judge is sales figures.
From this perspective, I'd understand why Joel would talk about bug fixes. But let's be honest, a "bug fix" that actually gets around a limitation of the underlying system is not a bug fix. It's an unnecessary kludge that could have been avoided if the system makers (in this case, mostly Microsoft), did their job and delivered something that works.
Redefining words is fun.
Those aren't bugs in the underlying system, they're how the interface works. If a MS API or POSIX or JavaScript or c++ or Haskel require you to use magic incantations you don't like the sound of to make them do what you want, it's frustrating, but it's not a bug, it's dealing with reality.
That reality you speak of has been forged by flawed fellow humans. Sometimes they make crappy interfaces. Sometimes the crap is undocumented. And more often than we care to admit, there's a genuine bug in the system we are relying on.
Getting around crappy interfaces should not be necessary. Dodging undocumented edge cases should not be needed. Getting around system bugs should not be the responsibility of the application developer.
There's the reality we can't change, and there's the reality we can rebel against with torches and pitchforks. Crappy interfaces, operating system bugs, CPU bugs, driver bugs… are the latter.
I agree with you, except to the degree that you characterize code written to conform to the underlying system as a bug.
Is code that abstracts away the difference between the windows file API and the POSIX file API a bug? Certainly not. Am I going to get rid of it as part of my migration to c++17? Definitely.
You can deprecate system idiosyncrasies and bugs without characterizing the code that conforms to them as being bugs, and pertinently for the discussion at hand, if you remove those workarounds in a rewrite, you broke the code.
How large is that component though. There's a world of difference between rewriting a sub-100k SLOC personal project and a many million SLOC enterprise product.
I don't think it is harder to read than write. I think people overestimate how difficult it is to read and underestimate how difficult it is to write.
Not only that, but tools for refactoring are poor in general and very poor in many languages. I want to at least be able to move variables around and have that changes trickle down to where they are used.
Reading code is relatively easy, understanding it isn't. As someone who's daily Job it is to plug holes in a 30yo codebase, most of my time is spend reverse engineering the code and figuring out what the purpose of the various parts is. And only something like 10% of the time am I writing actual code. Sure I can spot quite quickly what someone is doing in their code, but not why. And understanding that bigger picture in an existing project is harder then writing it. And crucial in order to improve on it.
Would you say commenting 'why' I do something a certain way would be good my own future self? (aspiring game dev here)
sfcpfc · 4 points · Posted at 21:42:08 on April 26, 2018 · (Permalink)
Yes, many devs would say that comments should be avoided in favour of writing self explanatory code (with descriptive function names, for instance), but some times that's just not possible. If why you're doing something isn't immediately obvious, comment the why.
I agree.
Writing code is more difficult and time consuming than reading it.
Writing code and the required tests is much more difficult and time consuming than reading it.
Writing code and the required tests and having it tested by users for days, weeks, months, years is even more difficult and time consuming.
Replacing existing code is difficult because it requires that the existing code must be read and understood first.
IMO the reasons for abandoning old code are:
- the old code has severe problems.
- the old code does no longer meet the requirements like e.g. being quickly usable and adaptable for a new project by new programmers.
Joel is/was full of shit. He might have been right on some points, but even then it was probably just coincidental. Do not take anything he says/said without a huge lump of NaCl.
Source: I've actually had to use some of the software his company produced (still produces? I hope not). It was so far behind the times that it was completely unusable. It did truly absurd things like requiring Flash to show a chart -- they didn't even bother to just have the server render an image and then <img/> that sucker. (Not that that example is an example of being behind the times... just customer-unfriendly in the extreme. I can only apologize -- I'm traumatized.)
In my world, the old code was likely written by a team of guys in India that went through some 3 week bootcamp and have no business writing code professionally.
Or it was written by a contractor/freelancer that got in over his head and jumped ship because why wouldn't he? He got paid up until the point at whiOr his overlords started adding bizarre feature requests that were out of scope as if they were in scope all along and he quit the project in a state of complete despair.
Or it was written by a chain of coders who each left the terrible project for their own reasons, with no overlap so none of the multitude of programmers had ever had a conversation, let alone a meeting, and the glue holding all of that together was some ridiculous, technically illiterate "entrepreneur" who thinks he has enough of a handle on his system to explain it to me, the way he explained it to the last four coders, all of which did things in their own peculiar way with no common process or methodology whatsoever.
Sometimes the project was initially started based on either some really odd, outdated technology or some hip, new, and worthless technology, but at any rate, not the right technology and anyone with any experience would know that except, well, this team.
Or the code is just unreadable because writing readable code seems to be hard to do for a lot of programmers.
Consequently, I have never taken over an existing project in my life. Luckily, its 2018 and I don't have to. That's a really nice luxury to have.
You just described my company’s development philosophy except you missed the part where central aspects of the system are owned by different departments who don’t communicate or share a budget.
[deleted] · 4 points · Posted at 18:10:33 on April 26, 2018 · (Permalink)
What is your metric for determining whether code is “a mess”? If it’s hard to read then it’s a mess. that’s how I look at it. That’s a bullshit apologist fundamental law and I disagree. If it’s easier to write than to read, and I have to understand it and make it work, and (again) it’s easier to write it than to read it, then I’m not gonna read it I’m gonna write it.
no old code is thrown away because it's harder to work with it and meet requirements then it's to write from scratch and swiftly meet current and future requirements.
Not only requirements change, but after following through with one strategy you start to realize its drawbacks and in place to design better system.
nobody will give you a reward if you managed to work with old code over someone who rewrote everything but was more productive in span of few years.
[deleted] · 4 points · Posted at 21:29:05 on April 26, 2018 · (Permalink)
Yo let's tag the Jagex moderators every time they mention spaghetti code and engine work.
I'm a consultant. I get called in over and over to help companies when their back is against the wall. I've seen plenty of these rewrites. They're usually an unmitigated disaster. Part of this is because I find that many developers really don't have a good understanding of how to fix legacy code. Instead, they say "the system is too unmaintainable and we need a rewrite." (And they usually believe it).
Rewrites are shiny and sexy and management, often lacking the deep technical knowledge, buys into this argument. What's worse, in one of the most risky things a business can do, the decision is almost always made on emotion rather than with a solid business case (cost analysis, risk analysis, alternatives, opportunity costs, and so on).
The primary arguments for a rewrite go like this:
You can have a cleaner architecture
The code is easier to maintain
You can hire more developers by shifting to a "popular" language.
You can make the impossible possible
Let's take those in reverse order.
You can sometimes find yourself with code that simply can't do what you want it to do. More than once I've seen Node projects rewritten in Go because Node, while great, simply doesn't handle CPU-intensive tasks well. Or that client who decided their code needed to be peer-to-peer instead of client-server. That's also a strong candidate for a rewrite. This happens sometimes, but having an insurmountable technical issue usually isn't the driving force in rewrites. Most of the time I find awful code that can still get the job done and it would take less work to fix the code than to rebuild an entire system from scratch.
If your code is written in Haskell or Smalltalk, both awesome languages, finding developers is hard, particularly if you want them to move to a small town in the middle of nowhere. If you rewrite to PHP or Java, finding developers usually isn't a problem. However, by definition, languages with a small developer base are less common, so fewer companies have this issue.
True story: I love the one company who called me about maintaining their Perl system after they decided to rewrite their flagship software in Java. The Perl system was earning them tens of millions of euros and had hundreds of customers. Two years into their rewrite, they were able to shift two of those customers to the Java system and they weren't developing new features for the Perl system. What's worse? Turns out that the problems with the Perl system were due to hiring devs who didn't understand architecture or databases. It probably would have taken about six months to fix the most pressing needs because they weren't facing that serious of a problem, but hey, rewrites are sexy!
That being said, sticking to less popular languages could lead you into technology lock-in.
For the "easier to maintain code", that usually depends on the cleaner architecture. But here's the rub: either you take the devs off the old code and put them on the new code, leaving the old code essentially unmaintained, or you hire new developers with less business knowledge and drive up your costs. In either scenario, capacity planning is a nightmare. The larger the system, the more likely it is to fail.
And so management starts to get worried, pushing the devs harder, and that nice, clean architecture gets worse and worse as "temporary hacks" become permanent and unclear specifications get implemented without understanding the consequences. Congrats! You're exchanging one pile of spaghetti for another!
I've seen this again and again and again. Companies go bankrupt over this. I have one client who only avoided bankruptcy because three years into their rewrite, they had managed to buy up several highly profitable companies. They eventually transitioned out of their core business due to that rewrite mess and relied on the profits of the companies they purchased.
In a landmark 1995 study, the Standish Group established that only about 17% of IT projects could be considered “fully successful,” another 52% were “challenged” (they didn't meet budget, quality or time goals) and 30% were “impaired or failed.” In a recent update of that study conducted for ComputerWorld, Standish examined 3,555 IT projects between 2003 and 2012 that had labor costs of at least $10 million and found that only 6.4% of [IT projects] were successful.
Seriously, why would you honestly pitch a rewrite when you know it's such a high-risk proposition if you can fix your existing issues and still have working code? Large projects fail all over the place and rewrites hurt companies!
Pro-tip: if you're a developer who's facing management that's dead-set on a rewrite even though you know you can fix the issues, don't say the word "refactor." It's become a toxic word to many people and can trigger strong emotions. Instead, agree with management and explain to them that to minimize risk, you want to keep the old system running while you do an "in-place rewrite." It can work wonders.
tsmc · 6 points · Posted at 14:58:05 on April 26, 2018 · (Permalink)
My rule: write your code for junior developers. This means not taking full advantage of all the features of a language just because you can, and if something is actually an objectively better design decision then drop a comment on why it is so. Sometimes I even insert an archived URL to the docs for the feature. I’ve gotten dinged for made-up code smells like “primitive obsession” (yes, this is a thing) but at the end of the day I am not seeking to fully express my creativity, I am not a craftsman, and there’s likely another human who will have to deal with my code under tighter constraints than I had.
I'd be cautious of this. How is a junior developer expected to grow unless they are introduced to new ideas/patterns? On top of that some junior developers just don't know the fundamentals of the language, or any language. I've worked with people who don't understand how to use map()
I'm always going to pick:
users.map(&:name)
over:
all_names = []
users.each do |user|
all_names.push user.name
end
all_names
The first is harder for a junior dev to read, but a senior dev can read it and understand whats happening more concisely. With the each loop I have to interpret what you're trying to do, with the map I know exactly whats being done
tsmc · 2 points · Posted at 22:27:44 on April 26, 2018 · (Permalink)
I think it's completely clear what's going on in each case. One is a few more lines of code, most of it bookkeeping that even a newbie should absorb at a glance. I'm not sure how well this would hold up for a nontrivial example. You do raise a good point regarding introducing juniors to new ideas. I've never been good at mentoring.
rush22 · 1 points · Posted at 23:02:46 on April 26, 2018 · (Permalink)
I wrote an internal tool that uses a single table Access database as the backend for this reason. It's only used by 4 or 5 people and the fact that I can say "Just install Access and open the file. Read the help of you need to." to any junior dev if something in it needs to be fixed is 10x more valuable than the slight performance hit and somewhat arcane, but well documented and supported, queries.
[deleted] · 1 points · Posted at 23:18:40 on April 26, 2018 · (Permalink)
primitive obsession
What, like using int instead of IntegerFactory.createInteger(new IntegerBuilderImpl().addOneHundred().addTen().addOne()) ?
tsmc · 1 points · Posted at 23:37:02 on April 26, 2018 · (Permalink)
That's the pathological case :) My reviewer's complaint was that I did not use classes to couple data and operations on the data, I used free functions on primitive data structures.
MpVpRb · 3 points · Posted at 15:36:10 on April 26, 2018 · (Permalink)
I would restate it as...
It's easier to create complexity than it is to understand it later
The code always ends up more complex than the original design
Most of the time it's because the initial design was incomplete, but it can also be that the programmers didn't think of the simple solution. Other times, after a large bunch of working code is in place, a change is required that doesn't fit. The adaptations and workarounds introduce more complexity
My old code is a mess. As time goes on you get better at programming which means you'll see new ways to refactor or optimize things.
Snoron · 2 points · Posted at 18:37:55 on April 26, 2018 · (Permalink)
That is usually the case, yeah... but every now and then I see an old function I can barely understand, but after some annoyance with working it out I realise how damn clever it was and I think goddamn how did I ever even come up with that, I'm a genius! :P
Just took a cursory glance at the netcat base. I don't completely understand it all, but it seems to be broken out into atomic functions that have sane and descriptive names.
If I had to work on this codebase, I could probably contribute something useful within a week or two. Not the case with the application I'm currently working on.
IMO: functional programming à la F# and friends is about shifting the balance of the work towards the author and away from the maintainer. That's what makes it valuable.
So your assertion is that functional programmers will always write great, easy to read code that works well all the time and there will be little need to fix or modify it forever and ever amen.
One thing I wish I could have told my younger programmer self is to not attempt to turn this one-off solution into a full generic solution for the next time someone has a similar problem.
Because as you start to make it generic, you have start to leak your abstractions - requiring everyone to understand everything about your solution before they can plug into it.
The useful shared code is very small library type functions.
Otherwise it's sometimes easier to simply start over.
For one project I wrote what I thought was a very minimal framework. Very basic functionality. Very simple model. The next time I wanted to use it, I realized I could rip out half of it. I quickly forked my own code, and created an even more minimal version.
I think code reuse is pushed in university. I saw an interesting article the other day. Don't have code reuse as a goal in itself but do avoid code duplication. I think that gets to the point quite well.
[deleted] · 3 points · Posted at 17:57:07 on April 26, 2018 · (Permalink)
There’s a reason that programmers always want to throw away old code and start over: they think the old code is a mess. They are probably wrong. The reason that they think the old code is a mess is because of a cardinal, fundamental law of programming: It’s harder to read code than to write it.
Well actually no. I also thought it's normal to always think your old code sucks, but I've reached a point where I find my old code pretty good, reusable, and readable. Going back 6-7 years even. I'm in this business for 20 years.
I do sometimes have to rewrite or extend it in parts, but that's normal, because requirements change and so the code may change. That's true not just for old code, but also new code.
I think people who constantly find their old code sucks have more to learn about reuse, and clean factoring and architecture (no I don't mean Clean Architecture TM but just architecture that's clean and modular).
The same applies for third party code. I don't find that all 3rd party code sucks. Some is really well factored and a lot of thought was put into it. But a good chunk of 3rd party code sucks simply because the people who wrote it were not experienced enough to write good code, and it's very easy, to me at least, to be specific about advice and feedback about where someone failed in their code in objective ways.
At some point it's not just about PoV or the difficulty of reading code. It's about the experience of the writer.
Factorio is a logistics game where you connected different widget machines together via conveyor belts. Late game the map can look like spaghetti.
When I played with a friend we would make machines then alter them to fit a certain need. But when it came time to modify the setup so we could scale the machine up ny friend would delete everything and start building from scratch with a bigger size in mind. He would do this even if I had made space to make the machine 2x-10x larger.
For him rebuilding from scratch was easier than spending a couple minutes figuring out how the original machine worked.
Funny, cause I just made a call to rewrite old code base from scratch. I had a Borland Turbo C codebase for MS-DOS written in 1995 to port to a modern Linux system with multiple changes in terms of functionalities. Old code probably was not shit but it sure looks like it from today's perspective. Who here would have tried to port instead of rewrite?
This is true, but it's also sociological. Maintenance has low career value and makes it hard for a programmer to justify himself, much less get a transfer to a green-field project. You often see engineers who get stuck on legacy maintenance, don't really distinguish themselves because they can't, and have to change companies if they want to write something new. But another way to get a better job, if you're good at politics, is to try to create one, which is why there's always a push to do it again and better.
It's also true that 99+ percent corporate code is unmanageable garbage. The problem is that, if the new system is written under the same deadline pressures as the old one– and often it is, if not under more deadline pressure since it's replacing something that already exists and seems to work– then it will be junk just like what it replaced. So, the temptation to rewrite it is strong, but it's exceedingly rare to have an executive climate that makes good code possible in the first place, so usually this involves replacing one pile of crap with another pile of crap.
There’s another fundamental law: Most programmers are mediocre (by definition), and they’re given ill-defined requirements with impossible deadlines.
deong · 3 points · Posted at 00:18:33 on April 27, 2018 · (Permalink)
I quibble on a detail. They're not probably wrong. They're very likely right. The old code really is god-awful. The mistake is thinking the new code won't be. Code doesn't age well. Comparing it to a Dodge Dart is facile, because the Dart is a car very much like every other car ever built. It doesn't need to change every month to support a new kind of road, petrol, atmosphere, and drivers who are suddenly 20 times bigger or smaller, and as a result, you don't need a specialized group of people whose job it is to always understand exactly how to alter it at the near molecular level. Any old mechanic will do, because it's the same as any other car and it just has to do car things.
Software is different. Working on Excel doesn't even prepare you for working on Lotus 123, let alone some custom banking software and World of Warcraft. Every piece of software is declared finished with no more than a handful of people in the world who knows how that piece of software works. The code doesn't rust, but those people's memories and employment statuses do.
That's why there's so much appetite for rewriting. Because you aren't one of the people who really knew how it worked, and over the years, it's been hacked at by people like you who didn't have that picture in their heads until it's held together with duct tape and gum. The problem is in thinking that the new version will be better. It may be better for you, because you get to be the guy who understands it all now, but over the lifetime of your code, the outcomes look the same. And you had to reinvent 20 years of bug fixes to get there.
Maybe if people FUCKING DOCUMENTED THEIR CODE we would be having a very different discussion. No, no, no you troglodyte, it doesn't 'explain itself.' No you horrible horrible person it does not! Code comments exist for a reason!
Joel makes one big assumption - that the developers behind the original codebase actually were competent.
The worst of the technical debt I've seen is of the type where the programmers reinvented the square wheel - for example, instead of using normal time synchronisation, they wrote their own server and client and then proceeded to reinvent a system to represent daylight savings, because they had also decided to store everything in local time.
The code then "grew hairs" not because of bug fixes, but rather because the original developers were too stupid or lazy to use a proven standard that existed when they wrote the code, because they didn't do their homework.
Sometimes the root cause has nothing to do with bug fixes or edge cases. Sometimes it really does need to be thrown out because the foundation is plain old incompetence.
I've thought this for years on this "joel says not to throw out old code!" topic. I've come across projects where I advocated throwing everything away and starting from scratch, then ... sometimes regretted that decision (sometimes not). There were times when I talked myself out of a 'start over', and just worked with what was there, and... lordy, that approach was almost always a losing approach (except for very trivial situations).
There's other assumptions that Joel seems to make:
you're part of a team of people, all of whom are working on this code full time
you have access to people (stakeholders or original devs) who can describe the earlier process
the current code is actually working properly
That last one has bitten me the most.
I've taken over projects from other people who are no longer on the project (or perhaps even with the company, or in some cases, not even alive any more). When taking a 'keep going and make mods' approach, what I usually come to find out is that I start getting more and more bug reports about stuff that never actually worked before, but it was never acknowledged by any one.
I was brought in to do a migration on a system 2 years ago. The second part was to 'fix a couple bugs'. Once I got talking to the end users, I got a flood of requests. "You're the first person we've talked to in 3 years who's ever been able to fix anything, ever".
Some were not even huge fixes. Click a button to download a PDF file - broken. Oh... hey - the person who wrote this did not understand what HTTP headers were and just dumped raw binary data from a file. Probably worked on IE7 when they first wrote it, maybe, but ... whatever.
There was little hope of rebuilding that from scratch, but also little hope of ever actually understanding the entirety of the codebase (which was, IIRC, hundreds of thousands of lines of codeigniter PHP). No runnable tests (there were a few, but it was some homegrown test tool - the few docs written years ago didn't work).
So... I was 'too expensive' to keep working on this, and it was offshored to a support team in eastern europe (with a stateside management team). I got a call about 6 months after that from the primary end-user client, indicating nothing of substance was still done, they were unhappy, etc.
This was not necessarily a situation where "rebuild!" was definitely a correct approach. TECHNICALLY, yes, but politically and businesswise, no. But... the management team had 0 idea how bad it actually was (there was no official issue tracker anywhere to keep track of things), and once you got in there, you realized it was really more bad than good.
So yeah, this idea that systems are always in a state where just dedicated refactoring is the 'right' answer may be a good starting point, but IME is not a universal truth.
Sometimes it really does need to be thrown out because the foundation is plain old incompetence.
Oh... yeah, other idea here. Or security. Trying to retrofit secure practices in an existing spaghetti codebase is a nightmare, and a real liability. I've dealt with more than a few systems were I advocate rebuild simply because I have no confidence that I can address glaring security holes in a cost-effective manner. And... if I am now on the hook for dealing with someone else's security issues, the stakes, for me, are too high to accept. I'm primarily coming in as a contractor/consultant; if I was being hired in to a permanent (heh) team for a full-time role, that might be a different story.
I just tried an interesting experiment. I asked two junior programmers, 1 year experience each, been in my company for same amount of time to do the following:
Programmer 1
Write me a function which takes an array of integers, and the number of integers in an array. IFF the sum of integers, and number of integers, are both even then return 1. IFF the sum of the integers, and number of integers are odd then return -1. Otherwise return 0.
Results
Took 9 minutes to write the function from start to finish (compiling, testing, running debugging, looking up)
It actually took 5mins 45seconds of engineering (discounting start up / compile times)
Programmer 2
Look at this function, explain what it does.
3m 50s had rough guess as to what it did and roughly understand but didn't get all nuances, didn't understand it was an odd / even test and how you would ever hit the zero comparison
9m 0s later asked for help from me (his lead), and understood the % was a remainder but still didn't grasp it was checking even / odd still didn't understand the return zero case
15m later fully understood the function and all nuances
Conslusions
The use of % operator confused programmer 2 who couldn't google it. Programmer 1 could google "odd / even" test and received the % operator information
Programmer 2 got a good, and probably working, understanding fairly quickly but didn't understand all nuances
Only after some help from lead did programmer 2 understand the code fully with it taking just under 3 times longer to read than to write
The Function written by programmer 1
int CheckWeights(int* Numbers, int32_t NumberOfWeights)
{
int totalValue = 0;
for (int i = 0; i < NumberOfWeights; i++)
{
totalValue += Numbers[i];
}
if (totalValue % 2 == 0 && NumberOfWeights % 2 == 0)
{
return 1;
}
else if (totalValue % 2 != 0 && NumberOfWeights % 2 != 0)
{
return -1;
}
else
{
return 0;
}
}
curious as to why comments were not a requirement. or any sort of unit test. it would have taken longer to write, but probably less time to read and comprehend, no?
It's bad code in a bad language with no comments and zero context.
Why would someone have to pass in the quantity of numbers instead of examine said numbers. Further its confusing to me that anyone could have not heard of % OR figure out at least that its called an operator and google % operator.
Just making a function called odd and even would have made it clear what the % was for and a comment like your explanation above would have made it crystal clear what the purpose was.
Your test mainly shows the cost of writing bad code.
(defn sum-and-count-of-integers-even [ints]
"Returns 1 if sum and count of list of integers INTS
is even -1 if both are odd else zero"
(let [sum-is-even (even? (apply + ints))
count-is-even (even? (count ints))]
(cond
(and sum-is-even count-is-even) 1
(and (not sum-is-even) (not count-is-even)) -1
:else 0)))
or
(defn sum-and-count-of-integers-even [ints]
"Returns 1 if sum and count of list of integers INTS
is even -1 if both are odd else zero"
(let [sum-of-ints (apply + ints)
count-of-ints (count ints)]
(cond (and (even? count-of-ints) (even? sum-of-ints)) 1
(and (odd? count-of-ints) (odd? sum-of-ints)) -1
:else 0)))
I've always felt that it's more a case of "Yes, the code is a mess" because once in production all code is a mess. We come up with these nice abstract models that satisfy 98% of the requirements, and then we start coding edge cases in response to bug reports - and that's where all the sloppy bits and pieces come from.
New developer shows up, looks at the codebase, has a mental model that's pristine that handles ... 98% of the requirements, and thinks "I can replace this mess with a much cleaner model" and they do
...and then they start coding the edge cases in response to bug reports...
Back in 1998 I was working with an Oracle DBA who loved Oracle's CASE tools, but she knew that at some point she would always have to start writing code, at which point she couldn't use the CASE tool any more, because the round-tripping would be broken.
We had a pool on how long into a project she could get before breaking the CASE tool...
In my experience, what I have started doing is incrementally improving. First starting with better variable names, better loops, better data structures within the function. Shorter functions, then changing the class.
Then you do that over and over, and the code basically refactors itself, a cleaner architecture shows up.
It's because of the forever changing trend and patterns and frameworks that comes and goes. If code is all pure logic it should never be an issue, but if framework of the day comes and goes, you throw away a lot of old code. How many here had to throw away Angular1 code?
piexil · 1 points · Posted at 14:54:31 on April 26, 2018 · (Permalink)
what about anybody who wrote anything with polymer, talk about something that just came and went.
Swie · 1 points · Posted at 15:31:51 on April 26, 2018 · (Permalink)
That's part of it, but also as a project progresses unforeseen requirements and problems are added, or change in importance. You can write a design that worked really well for your original predictions of what you would need to support, but after X years what you need to support may have changed dramatically so your design must change as well.
Or sometimes the features didn't change that much but the programmer's understanding of the required logic/design did.
ltjbr · 1 points · Posted at 16:33:59 on April 26, 2018 · (Permalink)
How many here had to throw away Angular1 code?
That's why it's always risky to go with the latest and greatest for any substantial project. Code Slingers might be frustrated by not doing the "cool stuff" but some times that stuff is only a fad. Now you're left with a poor front end stack no one likes solely because it was the hot tech at the time.
Smart companies have the guts to say no to the devs pushing for cutting edge tech.
Some devs might leave, but that's not necessarily a bad thing. You want devs that care about what's being delivered and work well with others, not devs that care about hip frameworks.
The reason that they think the old code is a mess is because of a cardinal, fundamental law of programming: It’s harder to read code than to write it.
Incorrect. The problem with legacy code is that it is hard to know if any change will not introduce a regression. It is impossible to know and test for all possible edge cases with legacy code. Even with perfectly readable and understandable code, there will still be edge-cases that are not obvious.
Which is why I love Feather's definition : "Legacy code is one that doesn't have automated tests". With automated tests, it doesn't matter if code is unreadable mess. It becomes trivial to experiment to figure out intended behavior and then refactor to improve readability.
With automated tests, it doesn't matter if code is an unreadable mess. It becomes trivial to experiment to figure out intended behavior
This assumes that the existing tests cover what you change. I see it every day when a whole family of tests exist for something, and the unknown unknown happens. Meaning a new test case didn't exist, or a component failed in a way that "should not have happened". Regressions can happen whether the code is "legacy" or not. The definition of legacy code:
Seems like one solution to "This code's crap and needs to be rewritten" from every new dev on the project would be to put new devs on the project to work improving unit test coverage. They get to write new code, they get familiar with the requirements and they get familiar with your code base. At some point they should start to realize why the code base is like that, and maybe they find and fix some actual bugs in the process.
Maybe it's just the book on software architecture I've been reading lately, but it seems to me that the biggest issue with crappy old code is the fundamental design. And if the design is shit with all kinds of circular dependency graphs, there is going to be huge technical debt that is going to impact future development. If you don't at some point redesign you are going to continually spend more development hours making less progress.
If something can be trivially addressed by a simple refactoring of a couple functions or classes, great. But I've seen a lot of applications written by developers (with a primarily procedural background) who haven't given any thought to architecture - only to delivering the product requested today as fast as possible, and when those applications get to be nearing 10 years old they are incredibly fragile and full of inscrutable code.
Even some of the best developers I know make shit architectural decisions in the name of productivity. Because you have to write 20x as much code to do things the right way when you can just insert this single line of business logic into the UI. But when you start inserting code anywhere you can make it work rather than the right place you are setting yourself up for a maintenance nightmare. The is the flip-side of "pragmatic programming" - it is important to be able to get the job delivered on time, but if you don't immediately turn around and do it the right way and the next developer comes along and creates a dependency on having done things the wrong way you have a mess on your hands. If there is too much pressure to deliver too fast, this is going to happen every time. Do this enough and a rewrite is the only way out, and the alternative is to pay 5 senior developers to deliver what one junior developer could in the same time without all that technical debt to contend with.
Depends on the programmer. Some get a concept working, then refactor. Sometimes you learn new practices and you inherently want to update old code. Some just shouldn't code.
It takes experience to know the difference between code that is difficult to read and bad code. Sometimes unreadable code alone is enough to refactor since code should be a document for other humans first. The only time you should stray from that is when you are forced to do odd things for optimization's sake. Then you just write a one paragraph comment apologizing for the hell you have created.
They didn't bring anything forward? I find that odd.
I often rewrite code, but i bring forward my good bits. And i do it because ive learned more since the last time i worked on the project in question and know whats wrong with it.
david · 2 points · Posted at 15:03:58 on April 26, 2018 · (Permalink)
I think the main problem is that we judge existing code on its achievements, but the planned rewrite on our aspirations.
There are times when a rewrite is the best solution, but it's hard to make a balanced assessment
On more than one occasion I've rewritten a function that I felt needed to be redone, only to compare it to the old one and realize it was pretty much the same thing.
Where I work, I am "the developer" -- nobody else is writing code. I tell my coworkers that someday when I retire, quit, or get the axe, whoever they get to replace me is going to tell them that all my code is crap and they'll need to rewrite it from scratch.
That person will probably be half-right, if only because (1) I'm human, not a coder-god and (2) technology will probably advance and there will be simpler ways to do what I did.
Even so, when that day comes, I have no qualms about that person doing whatever they feel they should do, because at that point, the code is their problem, and they have to live with the choices, not me.
You now what got me past the urge to rewrite everything written by those who came before me?
Actually rewriting some of it.
Now? If it ain't broke, I ain't fixing it. I don't care how shitty the code is, and some of it is really bad. It gets the job done and that's good enough.
Every now and then I'll end up rewriting small sections as part of another project, but only when it's quick and makes sense to do so in the context of the project. But that's it.
I rewrote a lot of my predecessor's stuff, but not because it was bad; mostly because it was small stuff that was written on an unfamiliar (or very dated) stack, or because the scope had changed and the original tech wasn't appropriate any more.
I didn't throw him under the bus, though; I always maintained that his code was great, but we just needed a rewrite. And truthfully, it was worth a few weeks of rewriting to be able to spend the next ten years maintaining my own code and designs.
ctorx · 2 points · Posted at 15:51:52 on April 26, 2018 · (Permalink)
It's easy to look at an antiquated piece of software and think you can bust out a newer better version but you are almost always wrong.
I have found that when I'm having the desire to rewrite something it's usually because I'm too lazy to dig in and wrap my head around the existing logic flow, which is often a long, cumbersome and confusing journey comprised of numerous iterations.
Almost always, once I have wrapped my head around the legacy software it's clear that there is nothing fundamentally wrong with it and that my disdain comes from the fact that it does not match my current idea of what good software looks like.
It's too bad this comment is so far down and will get mostly ignored.
As I told somebody else, the only time I'll rewrite stuff is when A) It's won't take too much time B) It makes sense to do so in the context of what I'm working on and C) I'm extremely certain that the new code will be a lot better.
Otherwise, if it's hard to understand, I just try to remember to add some comments.
Ehhhh, this is a pretty optimistic view of things. Old code wasn't carved in stone and sat there in production being perfect for decades. Old code had bugs that needed to be fixed. And people didn't fix those bugs perfectly and flawlessly. They stacked band-aids on top of band-aids and made the code shittier as they went.
The old code isn't "proven and flawless". It does the things the production environment demanded of it, but that's not what it was designed to do or what you want to do with it now.
So yeah, sometimes you have to decide between putting another band-aid on it or replace from scratch. Two hard choices, but eventually it has to be done.
This is one of those arguments that sounds insightful, superficially.
But how many large systems did he personally examine before making this claim? Was it hundreds? Surely not thousands. Was it dozens? Was it two or three? Were they even that big or old?
Some of the code I maintain and modify has comments in it from the early 1990s. That's not bragging, fairly certain more than a few people could one-up me by decades. But it's old and big and there are single-source-code-file applications that are 30,000 lines or more of spaghetti.
I don't want to start over. That's insanity. I'd like to rewrite it while dissecting the original on the pathology table right next to the new model. Go over it line by line maybe.
Fuck, the wonders I could do if I could just get rid of the comments and chuck those into git commit messages. Or to get rid of commented-out-code.
Actually though, I don't care enough about this shit to want to do that. I'm talking more theoretically like in some ideal job where it matters. It's all bailing wire and duct tape here.
Notice how every piece of software mentioned is basically now irrelevant to non-existent?
Code reuse isn't hard. That's why we have libraries, DLLs, objects, and so forth. It makes it easier.
This is why code reuse is so hard. This is why everybody on your team has a different function they like to use for splitting strings into arrays of strings. They write their own function because it’s easier and more fun than figuring out how the old function works.
Fuck functional programming!
There's your problem.
“Well,” they say, “look at this function. It is two pages long! None of this stuff belongs in there! I don’t know what half of these API calls are for.”
Again. If you don't understand your fundamental libraries... nothing is going to fix that besides learning them. A lot of programmers waste time writing functions for APIs that are vastly superior to them. And it is hard to understand, literally.
As if source code rusted.
Of course it rusts. 32 bit code is junk. 16 bit code is utter garbage. 64 bit is king!
The idea that new code is better than old is patently absurd.
This was written before 64 bit processors. So I'm just going to digress from here on out.
edit: btw, I totally agree. Jibberish code is what I call it. Reading shitty code is shitty. Then again, plenty of software has been rewritten from the ground up. Case in point: 9x vs NT. Fan-fucking-tastic! The only way to truly evolve is to start over. Maybe not entirely, but certainly predominantly.
Speaking from experience: my best improvements to my own algorithms have been when I started over. When I looked at my code and concluded: this does not work. I started fresh. I asked other programmers for input. I got ideas for vastly superior algorithms and used them and the results vastly improved and the efficiency vastly improved. And typically reading the code... yup! that improved, too.
Throwing away code can certainly be worth it. For instance, your codebase may be so bad that rewriting it would save you a great deal of time and money down the road. Obviously, this is easier said than done -- the new code may wind up being just as bad as the old (unfortunately, most software engineers are awful at architecting).
And I think it's a bit disingenuous for the author to suggest that Netscape's decision to rewrite their code has caused their market share to decline over the past 3 years. I mean, it's probably been 10 years since I last thought about Netscape or heard anyone mention it, so how many users could they have possibly lost?
I have maintained this awareness on my current project by sheer force of personality.
So far, my experience has been that: we've moved from throwing away 100% (and copying 50% back in); to throwing away closer-and-closer to 50%, over time.
We seem to actually move marginally slower, but we, so far, have not introduced any defects into release. That is a depressingly massive improvement.
All in all, the difference is frustratingly less than I'd hoped, but positive. I think as we emotionally accept this approach, things may improve even more.
A lot of this makes sense, but there are occasions where you really do have no choice. There may be a few reasons, but the one reason I can think of off the top of my head is that your application may have outgrown its underlying tech.
For instance, you may have written an application in a scripting language, found that it has outgrown that and now needs to be written in a language that can be natively compiled. It doesn't matter why it started in the scripting language (maybe it was short sighted thinking, maybe the growth was not expected when it was conceived, who knows).
Other than that though, I agree with this post. A perfect example is Blender. It has a very complicated and unwieldy codebase, and the first instinct when you work with it is that you want to throw it away and start from scratch. But, at the end of the day, that 20 year old unwieldy codebase produces a fantastic product that gets the job done. The end user does not care what is going on under the hood, just that it does its job well. Any problems with that codebase can be fixed with comments and a bit of reorganization; no need to throw it away.
[deleted] · 2 points · Posted at 19:34:01 on April 26, 2018 · (Permalink)
I'm reading that article just thinking, these programmers you're talking about must not be very good. Everybody writing their own string splitting functions? Code reuse is hard? Come on.
Also, every system gets built and then added onto over time. Eventually all those additions to hack in new features that were not part of the original design start to create a mess. At some point you've learned a lot, technology has improved, you have a clearer vision of what the application needs to do, and there are plenty of places where things could work much better if they were designed to work together.
Of course starting from scratch will have challenges, not the last of which is trying to make sure the new app does everything the old app did, and catches all those word cases you codes for but may not have documented (though there are ways to mitigate this). But that doesn't mean it's stupid.
Just make sure your developers are competent enough to do the job.
Edit: this article is 18 years old. I thought the mention of Netscape was weird but I didn't catch it at first. A lot has changed in 18 years. No wonder his developers sounded stupid.
This is only true for the age we are in development in which most old projects comes as monolithic wall of text spread across few files.
Even when they are done using an mvc framework, the probability of the original programmer not following the guidelines and writing a mess of hacks and workaround because it didn't want to waste time reading the doc (or the doc being missing) are very high.
This is also the main problem I find in JS framework. Most of the framework make a pride of being unopinionated but considering that the disciplined developers are quite rare, that's not really a plus in my book.
Lately I'be given a round to Angular and Vue, working in a company that used exclusively AngularJs. I found Angular to be quite promising in giving direction and kinda forcing the Devs to follows a path. This if you use the excellent CLI.
Vue is quite interesting, the only thing I find bothering is that the CLI seems to only create components in a single .Vue file, which is interesting if you're writing a web component but not much of you're writing a complex frontend application imho.
All in all, CLI and blueprint are the saviours imho.
While this is probably sometimes true, I can't comprehend how a human can be so dumb to just generalize all situations like this. And these are the "thought leaders" of our world.
I was watching "Antitrust" on Hulu the other day and had a good laugh over the HTML floating in the background of the opening credits. Then later on in the film, the characters would cream themselves after looking at code for a split second, saying how amazing it was. Hollywood coders are hilarious.
There is also this fact that it's fun to write code from scratch.
[deleted] · 2 points · Posted at 21:43:25 on April 26, 2018 · (Permalink)
I usually start over when the underlying architecture can’t support scalability with capacity and new feature support. Or when I’ve added so much spaghetti code, it’s now unmanageable.
I often find I don't full understand a problem until I've finished writing the code and gotten it running. Then in the course of debugging it I will often discover new things.
A year later I may try to refactor and rewrite the code, and it will come out better again.
And a year after that once more. Usually by the third rewrite there is nothing left to trim and no more performance to squeeze out.
And a few years after that when the code has been used in several projects and never had a problem or needed any rewriting and I've never looked at it and said "why did i do that?" then I know it's fully mature.
I rewrite code because I always find that I've learned so much since I originally wrote it.
GISftw · 2 points · Posted at 22:12:41 on April 26, 2018 · (Permalink)
I think what Joel is saying means "at a large scale". Of course it is almost always a bad idea to redo an entire functioning product code base all at once. It is not always a bad idea to redo small pieces over time as requirements change. Eventually you might replace the whole code base, but the entire time you would have maintained a functional product.
Of course, I say "redo" not "throw away"... you have to read the previous code (and probably some of its previous revisions) to gain the historical knowledge of why it exists in its current form. Joel mentions many esoteric bug fixes over time that add up to ugly code, but if those are properly commented/documented, then you won't lose them when you redo the code.
That being said, there are a lot of bad programmers out there and thus a lot of bad code. This especially holds true in the modern web scale world where speed to market often takes precedence over proper architecture. There is a reason your website requires 10x more server resources than you thought it would...
It's actually the opposite, if it's code you wrote recently.
They want to rip it up because 99% of projects start with an incomplete understanding of what the real requirements are.
Check that. it's 100%.
And by the time you're half done, you realize you should be coming at it from an entirely different direction because you finally grok what the requirements should have been all along.
This post is from 2000 but I think it might be pretty prophetic: most code I see is intentless, ugly throwaway code. As if we, as a profession, as a culture, do not embrace best practices and have to reinvent the wheel again and again...
Ive never had that throw away code mentality, for whatever reason. Its probably harmed me in some ways, because I will always try to modify code as little as possible even when it might make sense to add a new system instead of cluttering an old one. Learning to balance when to write new code vs using old systems can be tricky.
TIL there's a law that states reading code is harder than writing it. I thought i was the only one who has more difficulty in reading code all this time. Wiser today now
Just responding to the headline as I didn't read the article (this is an internet comment, after all), but that is completely ass backwards. Reading is easy, writing is a skill that takes work to develop. Children can read, and relatively young people can read well–very few people can write well.
There's no prize for reading, yet there are many for writing, and programming isn't somehow magically different than the other communicative endeavors of humanity.
You want better code? Give people more time and a better and more extensive editorial feedback loop on their writing. Harper Lee had an editor; you're not better than Harper Lee.
I don't think that's it at all. Old code bases accumulate technical debt. When confronted with this, a new person on a project often immediately sees this stuff and is like "why the hell are they doing it that way?"
Of course - but the problem is the myth of the "complete rewrite". Huge costs to get the same thing but prettier code? Paying twice for the same thing?
I never suggested "The Complete Rewrite" was a good idea, I was just saying it's dismissive and conceited to suggest that new members of a project who think legacy code is ugly and would like to rewrite it given the opportunity are wrong, and that instead it's good code but they're just too lazy to read it properly.
Sorry, I didn't mean to imply that you suggested that, I meant that yes, you're right, the problem is often that folks jump to the wrong conclusion regarding the best solution to that problem.
The code might very well be shit - but it's a polished, experienced turd. The solution to the unreadability is not to throw it away, but to slog through it and refactor and test it. While doing that one will surely learn a lot.
But sometimes even that won't work... what do you do then?
It depends on what you mean by "work." It's not clear what the root problem is. If all we're trying to solve for is elegance, some times you need to bite the bullet and accept that occasionally "if it ain't broke, don't fix it" is appropeiate. If maintenance is becoming a problem, do your best to isolate components and replace it btick-by-brick (on your maintenance schedule) with a more versatile/modular solution.
The code might very well be shit - but it's a polished, experienced turd. The solution to the unreadability is not to throw it away, but to slog through it and refactor and test it. While doing that one will surely learn a lot.
I wrote a longer post somewhere else, but the big assumption here is that this codebase, however ugly or difficult, actually does work as people are wanting it to. When that's the case, yes, but the bullet and deal with ugly/difficult/inelegant code.
I've come in to tech projects where, once you dig in, it's found out that much of X isn't actually working as expected, but users are just working around the bugs (laura just ignores the daily report button and compiles her own every day because the report button takes 3 hours and the data is wrong 80% of the time). Depending on the severity of these issues, that may or may not justify the "complete" (or mostly complete) rewrite, but... the assumptions in the "never rewrite!" are that the code/systems work, and are just ugly/difficult.
Of course, there are never easy solutions or answers - never rewrite is obviously wrong when what you're dealing with is not actually working.
I actually have that issue right now - we have a component in the software we're working with, sort of like a modular scripting tool - user can drag and drop modules that take input, does stuff with input, has output. Sounds at least somewhat straight forward.
The code is fucking backwards. The architecture is just... wrong? Modules are not standardized, they do not have formalized inputs or outputs, like there is no IModule interface, the structure is not a straight list for some reason but a weird tree which just makes stuff more complicated than necessary (you will never ever have a cloud of stuff in this thing) and all the modules do their thing in different ways... so everything is broken, code-wise.
And the only customer basically only works with this thing and there are bugs in literally every module - so, do we fix all the bugs in this mess or write a new thing?
I say write a new thing and reuse algorithms. Perhaps some automated tests in there?
But the software is much larger than that one component, so it would be silly to rewrite the entire application - we just need to figure out a cleaner architecture for this one thing and fix it so we can add features and fix bugs without going insane.
If you have ever seen untestable code, this is it. Dependency injection is complicated - so every dependency is a singleton. WHAAT?!
A property might load a file when accessed.
Every class just randomly instantiates database connections.
It is a hot mess. But the ideas are sound, we just need to rewrite that fucking mess.
There's another aspect I'm not sure I explicitly put in before, but was on my mind - security. If something is so "messed up" that no one can understand it, and have trouble even keeping up with bugs... it's probably going to have unknown security issues. Just rebuilding with a known set of good libraries or framework will force you in to some patterns which will avoid common security errors.
A property might load a file when accessed.
WOW....
Had a system years ago which did a lot during a constructor - like... include multiple other files, did about 15 DB queries, logged info, and might send an email under certain situations. I asked to modify that to an 'init' or 'setup' method, so that I could reuse the class, and... no one understood why.
It's experiences like this where the Joel stuff really needs some asterisk on it, explaining the assumption that the rest of the team is competent. Yeah, I know this sounds harsh, and... I've been the incompetent person on a team a couple times early on in my career (sorry previous colleagues!). But the assumptions may lead people to make suboptimal decisions...
Not a security issue so much but was just dealing with some small web app which I'm trying to add a bit of functionality too. Had this been done with some normal framework, (this is a PHP app), adding my new stuff and making the mods would have taken around an hour. It's taken about 4 hours so far, and I'm not done. Everything is global. File X loads something else which parses some vars and sets a bunch of required vars - great, I can reuse that in what I need. Nope - it also sends emails whenever it's loaded. Yeah, it saved the original people some time to 'slap' this together, but... it's now multiple times more complex to touch - and... it still needs to have every query rewritten because they're all open to SQL injection. This is another example of rebuilding with good tools would probably have taken just a long as the 'small upgrade', and I'd feel much better about the fundamental foundations, instead of reactionary patching what I happen to spot. Perhaps this is what we should mean by 'reactive' programming? :)
Jesus... your story reminds me of a classic asp site I got my hands on once... it was made by one of the employee's sons during a summer break or something.
It was all sorts of strange. It had include files. Like all pages included include.asp. Which included 10 more files. All of those included like any number of files... aaah...
And you know, it's written 30 years ago when there was less knowledge on how to structure and work with large code projects and just worse languages etc. Code can be outdated even without bias you know.
oserna · 2 points · Posted at 05:40:18 on April 27, 2018 · (Permalink)
In the last 20 years (like the 20 years before that) the quality of software, and the performance of programmers has increased massively. It's largely analogous to the performance improvements of athletes and other specialist activities like chess. The world has moved on, and it leaves old coding styles and techniques behind.
A large part of my previous job was working with code bases of that vintage, i.e. late 90s and early 2000s for retail POS and backend systems. And f**k me was that a PITA.
In the next 20 years, the majority of our current code base will be re-written. It's inevitable.
The question is not, if it should be re-written, but when
I'm not sure mate, if I inspect code from my early days and now realize I could achieve the same thing with 1/4th the code maybe my old code is actually a mess...
I don't really agree with the statement.
Most of the time when I rewrite projects, mostly personal ones, it's because i evolved over time, I know how to make it better and more efficient.
part of the problem is a weak understanding of the architecture. Rather than fix the core problems, the code gets hacked to bits. In time its just a mess that barely works.
I liken it to adding something to a car. Youre not quite sure how to properly install a new stereo, so you just poke around until you can get 12 volts from ...anywhere. Then run wires to the sub in the backseat. no understanding of how the thing is supposed to work, and you probably have limited time to make it work...so ill just steal 12v from the cigarette lighter.
do that enough times, and your car just catches fire.
but sometimes the code IS a mess. Even veteran programmers just zero in on a quick fix to get the problem solved, which over time creates the very same problem.
izackp · 2 points · Posted at 13:53:58 on June 13, 2018 · (Permalink)
I'd rather refactor code then create it from scratch. In fact, I learn the most as a programmer by reading other people's code.
It's an incomplete truth. Most code is poorly architected, so there's no implicate order for the mind to latch onto. Well-architected code is a pleasure to read and obviously correct.
ngroot · 3 points · Posted at 14:49:20 on April 26, 2018 · (Permalink)
If the code is hard to read, someone didn't finish writing it.
Well, that part is probably true. But, starting over, and over, and over, is like rehearsing a theatrical. Every time you rehearse, you get a better understanding of the whole project. Eventually, you come to the dress rehearsal, and then, performance! Unfortunately, business timetables tend to go straight from proposal to performance and, thus, to defeat quality.
It was hard to read your title, so I wrote my own: "It's harder to read code than write it, just throw it away"
pukatm · 2 points · Posted at 15:47:49 on April 26, 2018 · (Permalink)
Is this "fundamental law" real or just hype and marketing stuff?
It's a very bold statement to suggest that a programmer is wrong to think that old code is a mess and is almost insulting. Software requirements change all the time and quickly. Programmer turnover rate is high. When an old and well-designed solution keeps being patched over and over again to cater for new unforeseen requirements under pressure, when the new guy on the block is inheriting code of questionable quality, reading isn't hard or effortful, but it is painful: more reading is uncovering more ugly implications (the programmer ends up responsible for the code at the end of the day) and stopping to rewrite is an effort at putting the programmer at ease (the programmer is now in a different mindset in which they can accept responsibilities because the solution becomes theirs). Software engineering is difficult.
🎙️ the_phet · -1 points · Posted at 15:56:29 on April 26, 2018 · (Permalink)
The fundamental law is that it is harder to read code than to write it. And this is very true.
pukatm · 1 points · Posted at 16:02:21 on April 26, 2018 · (Permalink)
To clarify: better to perform some studies before going as far as saying these things are a "law"... This isn't very true just because you say so... I hope!
Krakob · 2 points · Posted at 18:42:59 on April 26, 2018 · (Permalink)
I appreciate that the headline gets straight to the point because let's be real, no one here actually read the article 😝
I am currently tasked with fixing a series of Java bugs identified by a linter. One group involves potential null pointer issues where there is a method (written, according to the VC, around 10 years ago) that may catch an exception, log it, and return null. Many of the calling methods don't have null checks. There is no way that this code is not a mess and fixing it would be the better option.
I'm sure in many cases Joel would be correct, but in my experience old code is often a massive unmanageable mess of items built on top of other items and hard-coded hacks put in due to time and budget constraints.
If you have code that you don't understand and no unit tests, write the unit tests. If you do have unit tests, read those instead. One of my rules of unit testing is to always go for readability first with very clear structure.
A big part of it is the human factor. People get into programming thinking it's just stuff they write, or at least that's the initial draw. Then when you realize your cto only cares about clients and your second in command only care about old ways of doing things, and bad code gets splattered everywhere. You begin to regret it and it never gets fixed cause well there are sprints. Which is just great for logical data driven design because well productivity is 1# always. Then as you work up you realize the real garbage and the humanity of lifers. It turns into one big incest fest of awful mess of making things productive. Then comes the newly hired terminator because features are taking too long....yay!
I've found it to be a spectrum [reads code well]-----------------------[writes code well]. I am definitely in the camp that I can code better than I can read it. I would also concede that it's probably not normally distributed, as the author suggests.
That said, I fundamentally believe in throwing out code often, and taking a prototypical approach mostly because we kid ourselves in trying to waterfall the requirements of a project. You can develop much better solutions once you've eaten the dog food, designed the system, seen the similarities, seen the performance issues, seen the security issues, etc etc etc.
For me it's more about hubris, in that we think we can ever really properly account for all the use cases without getting our hands dirty.
It also goes into testing. There's a lot of hubris there as well. On the day you start working on a feature, you write your tests, your tests are now hard-coupled to the exact same set of use cases that your working code expresses. But what is a very common type of bug? A missing use case! How do you test for that with certainty? You can't test what you don't know. In the same vein, you can't design a system for things you don't know, even when you have the best design team possible, and are free of "we need to get this into the project by Friday" type asshattery.
The tl;dr is that the best code blends the old and the new. Carry forward healthy pieces of code, along with their battle hardened tests, but re-design things that are square pegs trying to fit in the round hole of the real context surrounding the project. All the while keeping in mind the extraordinarily high value of running, working code. It's about balance, more than extremes.
[deleted] · 1 points · Posted at 15:29:38 on April 26, 2018 · (Permalink)
or we just grow our skills and old code IS terrible
When it comes to my code, the old code can't be reused because it worked well for the technologies back then. More often than not, the code was to integrate with particular version of frameworks (be it database, web service, cryptographic or else) that were acceptable for that time. To give a quick example, my old code used MD5 to hash and LINQ-to-SQL to access the database and it used WCF to call web APIs. It's unimaginable that any of that code is reusable, because it's deeply connected to obsolete or insecure technologies.
Another main reason to abandon old code is that we keep learning new techniques and old code didn't not take advantages of these new knowledge that we've learned. Take 2FA and QR code, for example, before knowing it, my application would send an email to verify a secure login, but now user just scans a QR code to setup 2FA for the first time and then use Google Authenticator on their phone to generate a 2FA code to verify their identity.
Last but not least, the old implementation is just wrong. There were times when I never heard of HMAC needed to verify decrypted data and I coded the encryption based on that assumption. Turns out... without HMAC, the encrypted data can never be verified later that it's not tampered with.
[deleted] · 1 points · Posted at 15:33:31 on April 26, 2018 · (Permalink)
Someone said programming is theory building. Humans are not very good at building formal theories and communicating those theories to others. I have yet to work on a codebase where intent, code, and documentation all align. Everything is always out of sync and a non-trivial portion of the bugs come from that misalignment.
I love Joel. And as usual for him, this is solid, traditional advice that I thoroughly agree with.
However, the era of modern programming may turn this traditional advice on its head.
We now live in the era where we have access to a vast number of open source, commercial friendly (BSD/MIT), extremely high quality purpose built libraries we can now take advantage of.
A large portion of old codebases are poorly thought out, hastily built, and bug ridden modules designed to do certain things. Caching libraries, event systems, pub/sub architectures. Custom IPC. Oh so much IPC.
When you look back at all these subsystems, nearly all of them can be replaced with highly performant, mature, open source libraries, packages, and services.
There is simply no reason nor justification for continuing to use and maintain all this old code that, turned upside down, looks like you are trying to reinvent the wheel, only very poorly.
When you look back at all these subsystems, nearly all of them can be replaced with highly performant, mature, open source libraries, packages, and services.
So what? He explicitly said you can replace parts of the application.
Because 90% of most applications are undifferentiated heavy lifting: things every large application needs to do, but isn't the business function of your specific application.
Open source has changed the nature of this by abstracting away nearly all of that.
If you are to swap out 90% of your application and save the 10% that is actually your unique competitive advantage, you are basically "throwing away your application" and starting over.
edapa · 1 points · Posted at 15:51:35 on April 26, 2018 · (Permalink)
I think a total rewrite of a large system is almost never a good idea, but if you are in a place where you are scared to rewrite individual modules or features it means you have a serious testing problem.
It's harder to write code that's easy for others to read. The earlier version was likely written under the gun on a short deadline to get a feature/product/system out, making it very likly they took readability short cuts, among many many other shortcuts.
It is still easier to fix the busted terrible code base than truly write from scratch, but that doesn't magically mean the busted version is good.
I had a class in University where on the programming part of the exam our professor would provide libraries that we needed to use/modify to do the specific tasks needed. The class was based on C++ and holy fuck me was it stressful to read and alter his libraries in half an hour, not to mention use them in conjunction with my own functions that he required we add.
Okay, so let's say you're given a codebase that is unreadable, barely passes tests, is lacking test coverage in a ton of places (i.e. bugs on the horizon) and was mostly maintained by one person that left the company some time ago.
You want to make the codebase cleaner, introduce more tests, etc.
Doing so will essentially force you to dump most of the codebase.
But this heap of shit is making the company $10M/month.
I think "thowing out code" needs to be differentiated from a rewrite.. and the difference could be that the high level to middle level design is changed when altering the code. In that case, it is a "throw away". Otherwise, it is just maintenance.
Right, and I'm not sure that this difference is made clearly here.
Moving the code around and making it cleaner without affecting the core of how it works == maintenance (lower risk, generally speaking)
Doing the above and changing core functionality == rewrite (high risk made lower through keeping higher level tests mostly intact)
Armchair a16z alert: After the first buy out, Netscape essentially created a new browser, meaning new everything, despite the fact that Netscape 4.x was mostly loved by its customers. This is super risky.
Seriously though... you fix it one step at a time. BECAUSE IT ALREADY WORKS. And if you think you can rewrite it and deploy a Version 1 that the customers think works as well as the old one, you're wrong. It's much better to spend all that time and energy improving the old one. Not only will the customers get happier as the product they already know how to use gets steadily better, they won't get all pissed off while your crappy Version 1 iterates it's way to being as good as the old product was.
While it is true that it is always harder to read code than to write it, even for the authors, how painful it will be to read varies.
I've worked on projects where developers actually don't make a complete mess.
And they I've worked on projects where developers seemed to feel that if nobody else could read their code, they'd have a job for life.
Unfortunately, nobody ever taught clean code when I went to school. Nor has it ever been demonstrated in any tutorials I've ever read trying to teach programmers a new language.
So, I can only imagine the typical developer has no clue what that really means and most code in the wild should be burned with fire.
I remember my first serious job - fixing bugs in a large system. Whenever we fixed bugs we would add unit tests to make sure the bug was fixed, but often times the unit tests felt like documentation of however the system happened to actually work, not how the system was supposed to work. Most of them would use mocks to say "make sure this method calls this other method and this third method." aka "make sure the implementation is the implementation." That's what bothers me about legacy code: the specification is "it should work the way it's been working" without careful evaluation of whether the way it's been working is the right way. Any code that's not actively throwing exceptions or showing noticeably wrong behavior right away is assumed to be correct.
Working with legacy systems inevitably leads me to the category of bug where I'm not asking "why won't this work?" But rather "how on Earth did this ever work in the first place?" Multiple fixes over the years to keep it working the same, not working correctly.
Most of them would use mocks to say "make sure this method calls this other method and this third method." aka "make sure the implementation is the implementation."
Agreed. That's a classic testing mistake. Tests should focus on behavior, not implementation. If I'm writing a test for translate object A into object B, I don't care how you implement that as long as it results in the correct value coming out the other end.
It's one of my dislikes of the C# Moq library examples, that they show setup of tests that verify if a method is called from inside the SUT. Fortunately, you don't have to follow that pattern to have Moq be useful.
I've tossed an entire code base before and started from scratch. As an architect it's sometimes easy to see fundamental flaws in the design post mortem, and sometimes it has to do with the technology that was used or the base approach to a problem. One example I can think of was a system that was "90% done" according to the manager. I took a look at it and realized that the entire system could be replace with a scheduled sql job. No need to build a scheduling system that runs a .net app that iterates through rows in a database when a single query that will run faster and be scheduled with a reliable job management system that we know works. Also, a majority of the code was shit.
What's to say when you actually make an honest assessment of a body of work and realize that it's just bad? Sometimes you can't polish a turd.
This was always the point I most disagreed with him about. I can't believe that every large codebase is of roughly the same quality, and the apparent differences are that subjective. Why would that be true? Maybe he just hadn't seen true spaghetti in production? I assert that I have seen true spaghetti in production, and that it caused serious problems over long periods of time, because of how it was written, not because of how we read it.
I'd be interested in anyone in this forum who is simultaneously a programmer but also someone who writes academic articles, and or creative fiction.
Because I find in writing essays, it is always better to completely rewrite than to adapt existing writing, because the overall logic to the argumentation can be reflowed more cleanly, even if you forget the details. However, in english writing and argumentation, the inverse is true to that stated mantra "it's harder to read code than it is to write it." Clearly in english writing, it's easier to read an argument than to write it.
I do this all the time with buggy arduino sketches
ekchew · 1 points · Posted at 16:40:23 on April 26, 2018 · (Permalink)
This is kind of what I picture in my head:
Merging old code into new project:
Patching Debugging
|-------| |--------------------|
Rewriting:
Coding Debugging
|--------------------------------| |------|
So yes, overall reusing should save time. But it's how it's spent man!
I keep meaning to write a thorough refutation of this article. If nothing else, let me say his examples have aged poorly and now show the opposite of what he thought. I don’t think anyone wants to emulate IE6 anymore.
I find I’m ok reading code that adheres to the Single Responsibility Principle. It’s just that most code tried to do ten things and you start having to hold a lot in your head at once to understand a single function.
For me its usually the opposite, a shot load of code that could be done in a couple of lines. Its often accompanies by a bit of database redesign, which I am not afraid of any more.
Absolutely not. I never throw away a code for I am a piece of shit who is great at using parts of other codes to make mine. I'm a horrible person but good at reading.
We have a 10 year old ASP WebForms system and I can assure you that it's not only hard to read but also hard to write. People are even scared to delete comments.
i mean. it'd help if there were comments. not even a lot. just fucking something.
fun facts: that old pinball game that came standard in the older Windows versions? they couldn't port it over because it was too buggy in windows 10, and there wasn't a single comment in the things coding so they had no idea how it worked.
want nice things? take the time to add comments.
Most of the time we go back and update old code essentially reading and writing it
m_krm · 1 points · Posted at 17:54:25 on April 26, 2018 · (Permalink)
Or there skills today are better then they were yesterday. And there knowledge of whatever language, framework or toolkit is more then what it was when that was wrote. Besides, it's more fun to build new stuff rather then to maintain someone elses legacy. 😀
Coding is as distinct to each person as our handwriting. Worked with brilliant coders and each one had problems reading the others.
l_hutz · 1 points · Posted at 18:06:34 on April 26, 2018 · (Permalink)
In my humble opinion;
The first rule of software engineering - there are no rules.
The second rule of software engineering - there are no rules.
The third rule of software engineering - there are still no rules apart from these three rules.
Also rule four: horses for courses. Some engineers like rewriting and refactoring. Some are good at working with what’s already there. I.e. See the first three rules again.
This advice bothers me for a couple of reasons, which I wrote up here[1]. First, I've participated in successful rewrites, and still think those were a good idea. Second and more importantly, most of the big tech companies we know and love (or hate) got their start by rewriting existing products. Google was a from-scratch rewrite of older search solutions. Facebook was a from-scratch rewrite of older social platforms. Etc. Just because it's a different team / company doing the rewrite doesn't mean it's not a rewrite.
Especially when it's anyone else's code but yours, or you were really really drunk during that period of your life.
dem_c · 1 points · Posted at 18:26:45 on April 26, 2018 · (Permalink)
When I find a new and better way to programm some thing, I end up writing the whole thing from scratch as implementing it to original cade would just make it more terrible
I, 100% of the time, look at a 'completed' program and just feel like there is a better way to do it.
That being said I find that often by writing the code on the fly and getting it into a working state, using that word losely here, I discover how the code should actually be designed, atleast in the parameters of my ability. After a little over a decade of programming, about half as a professional, I am still never really satisfied with my code.
Excuse my ignorance, i'm not versed in any programming languages but wouldn't it be easier to read with a demarcation explaining what given sections do?, i'm asks ming notations exist but also that they are probably fucking annoying, and lead to formatting errors. So wouldn't it make since to just highlight a section of code in certain colors as you write it, having an application to take care of this might be complicated at first but if it doesn't already exist i'm sure this would make reading code much easier especially if an etiquette surrounding highlighting developed.
but wouldn't it be easier to read with a demarcation explaining what given sections do?
In languages with methods/functions, you should be pushing those sections down into separate methods with descriptive names. Then it gets easier to understand the flow (less lines to look at) compared to getting lost in the details of how the flow is implemented.
Modern IDEs also have block outlining where you can hide the interior of the block between braces / brackets. That helps a bit too.
It's not fundamental, so much as a lack of training and/or discipline. See Donald Knuth's "literate programming". It's possible to adapt much of it to typical coding environments.
cs117x · 1 points · Posted at 18:52:53 on April 26, 2018 · (Permalink)
I don't really have a problem reading old code I wrote, I have had issues with reading others. But yea I guess redoing something your way can be easier at times, but I feel like this doesn't apply to boiler plate code.
Step 1 : look at old code, declare outdated/unreadable and explain to collegues how you can make it better.
Step 2: scrap old code
Step 3 : while coding realise the initial idea you had won't work.
Step 4: struggle pointlessly to get a solution working within the sprint
Step 5: end up with the same solution you scrapped.
you write something with a plan, the plan changes. requirements change. it's just a small change so nobody gives it much thought. 200 small changes later the code base is a mess.
Or, hey Xslt is really cool. let's go write everything in xslt. ah it's 12 years later and it's really hard to find developers to maintain this stuff because xslt is dead.
Or. you've got 20 coders working on different pieces of the pie. each team makes their own utility modules and does things a different way.
There are good ways to rewrite a whole codebase if the code is really bad. You do it slowly, over time, replacing bits of code with other ones. You can't halt development for it, nor can you have a separate team doing the rewrite - the guys working on the codebase itself need to slowly update it.
There's a difference between code that's difficult to understand, and code that's irretrievably broken. Very often the former leads into the latter as people rush to fix issues without understanding how shit works because it's too damn difficult to understand, but there's still worlds of difference.
Generally when you get to an irretrievable mess there are a lot more problems than just code. Lack of documentation, lack of feature specs, rigid micromanagement, lack of funding for QA, little to no standards for anything, technical leads that don't know what they are doing...when a project goes tits up it's more than poor coding...it's poor management. When it's that bad it doesn't often get fixed either.
There can be many reasons for the "burn it down and start over" reaction. Some are legitimate reasons and some are not.
The thing is complex and difficult to understand and the developer isn't familiar with all of the nuances, as pointed out by the article.
The thing doesn't conform to company standards, making it more difficult to understand due to unfamiliarity.
The thing doesn't conform to the developer's design/pattern flavor of the week.
The thing was poorly designed or implemented to begin with.
The code may have been nice and clean to begin with, but has been subjected to numerous updates due to bug fixes and changing requirements over the years, and grew into a patchwork horror. Cleaning these up can be cathartic.
It usually happens when transferring from one programmer to another. The question is whether it's the new programmer OR the code that sucks. Often it's both and that's why it's so important to have qualified programmers in management.
If it is a project that is maintained and grown over time then the likelihood of the code actually being a mess is huge.
Feature creep is real and features added down the road tend to be done without consideration to making that feature accessible outside of the current desired scope. Alternatively it is also common for existing accessibility to be removed in favor of optimization.
The worst is when you have a client with an ancient application that was:
Written in-house
All wheels have been reinvented (no existing frameworks or libraries)
The guy who wrote it is long gone
Features have been piled on by other developers that did not care to keep the same conventions as the original developer.
The people who added features are long gone
There is no revision history other than a few files ending in .bak or .1
The majority of the original functionality is no longer used (ie specialized for certain equipment but they no longer use that equipment) but can't be removed from the code without rewriting significant portions.
There are definitely times where rewriting is not only more beneficial down the road but may actually be faster than hacking in the new feature.
[deleted] · 1 points · Posted at 20:25:39 on April 26, 2018 · (Permalink)
Sometimes it's code where I didn't know the newer or better techniques available.
If working in new or fast changing languages better patterns / architectures emerge.
The key is to prevent as much repetitive code as possible. Use base classes/inheritance. Use helper classes and build util libraries. Any code that's not self evident what it does should have comments. That way refactors only have to hit one or a few places instead every code file.
I've never had issue refactoring my own code, other people's code however....
One of my college programming professors said something that pretty much as applied my entire programming career, changing code is always a much longer time consuming task than writing new code.
So we will be keeping that one file that somehow, through a black box of code, is compiled and run on demand in VB6. It contains over 2000 lines of code that lives in a handful of functions. And we customize this file on a per customer basis, mind you.
And we will be keeping the front end in VB6, where we are constrained by memory and addressing limitations. With it's terrible IDE and horrendous syntax. Not to mention how well it works with Windows 10 (Sarcasm)
And all those stored procedures written by a database dev that got fired too late into his cycle of work here? Are we keeping those too?
Fear of rewriting something is screwing this industry so hard. We are constantly aiming for progress, progress, progress and never anything stable and sustainable. Our work shouldn't be just about the customer, but about the developers who maintain it.
Let me put it this way: If you had the opportunity to stay in 'merica with a lot of debt(and work to pay it off) or just move to another country and not have to pay debt?
This is completely true, but there are other factors involved as well that have nothing to do with how difficult it can be to understand someone else's code.
Codebases [at least active ones] are like a living thing - they are constantly changing to accommodate new features and functionality, new design patters, new libraries or modules, etc. So while the existing code very well may have been the best it could possibly be at the time it was written, adapting it to fit in with the rest of the codebase may be far more effort than just rewriting it.
This point is underscored if you ever go back and look at your own code - this somewhat lessens the argument that reading code is harder than writing it because you did in fact write it and should have some basic memory of how it works. And yet, even in this case, a rewrite is very often the preferred approach.
This isn't just programming. I feel this way about excel as well. My main job is building dashboard reports using Microsoft BI Suite and I am much better at building the reports than I am at going back and figuring out where I went wrong somewhere.
Its worse than that, trying to build up all the context and background in your head takes a lot of time. Its easier to do targeted fixes but larger ones that require fundamental design changes are expensive and risky without a lot of context.
It can be easier to rewrite or layer and slowly consume the older code than to attempt to modify or maintain older code for this reason.
At least where I work, everyone uses different languages, and they think their language is better. Usually the younger the programmer is, the more often they want to innovate and do new things.
When in reality, you probably don't need to touch the old code base and things are there for a reason. But no matter what it is, big or small, its always "easier" to rewrite it in a new language and completely throw out the old code.
I am all for moving to a new code base or look at redoing some crappy code, but I haven't found too much of it.
Is it ideal code? no. Is it really that awful though? NO!
I always laugh when I see some guy who has been programming for 2 years come in and make fun of code that was written by a guy with 25 years behind him. That 25 yr guy made mistakes sure, and the language used is a bit or completely outdated. But its written well, its functional.
In my limited experience, code is a compromise between planning, time constraints and project management/constraints.
You start out cleanly, will a plan well thought out, for the given project constraint and attempt to satisfy that problem within the time constraints. Then the project constraint shifts, because the client changes their mind. A lot. And you are expected to keep up, but due to the time constraints, you cannot keep up with planning and refractoring. So you end up adding stuff everywhere and stuff gets messy. And you keep on piling on small fixes and addendums and abuse functions, until you either run into a dead end where you have to refractor or you miraculously get enough time and ressources allocated to refractor because the change you are making appears large enough to the client/project leader.
So having clean code sadly usually means you spent more money than you should have and more time than you should have. Maybe you can justify it by saying it is for safety reasons or to plan ahead for the future, but with most projects, cleaning up the code after having worked on it for a while is a luxury few can afford.
No. I don’t want to be wasting time debugging, researching something specific, or designing code for some small detail in a program when I’ve already developed it before. If you write it abstract enough initially, you can reuse your old code without wasting time cycling through a process over and over.
It is always good to be versatile and know how to code a feature again from the ground up, but if you create code in the first place where the input and output of each part is clear, you’ve built yourself a tool, and like any other tool, it can be used again and again for a variety of applications. Writing code that is adaptable allows you to focus on the original idea without being derailed or discouraged by the minutia of implementing features again.
"Good" code is written to be read! The old code is "bad" precisely because it can't be easily read and understood. Which side of this line your code is on is a big part of what it means to practice code craftsmanship.
every coder has a different style. if you're ona team, you need to conform to the standards set. if this a direct client or project, then yes, there is a good reason to start over. if you're going to be key programmer on the project, it should be your code. if the client or project has a problem with starting over, too bad. they can't expect to invest in a programmer, and fire them, and expect there not to be costs, like rebuilding the entire project.
Since code relies on lines and always (?) has some kind of "go to line x" or "refer to line x" couldn't you scan for a mention of a line or lines outside the section to be deleted to be sure it's junk?
If answering this question is too time consuming to bother sating my curiosity, I'll happily accept a "you are missing some core concepts that keep you from understanding" type answer.
Modern compilers will generally warn you if they detect unreachable code. Removing dead code is not the big challenge! Programs are designed to satisfy some requirements. Good design will let a program get updated in some simple ways as the requirements evolve. The problem is that requirement often evolve in ways that nobody anticipated. So all kinds of glop gets hacked in to manage whatever, a link to some other system etc. If you'd know what the requirements were going to become, you could have built in all the necessary doodads. But really nobody is that smart. Few things are as difficult to predict as the future.
Pretty much the reason I dumped Perl many years ago. I wrote a bunch of things, then found when I was asked to make changes, that it was painful reading that old code. I rewrote everything in python and never looked back.
Some of my own code is straightforward to read, it actually looks very obvious, but it wasn't so easy to write, and it probably was re-written a couple of times.
In fact, a lot of refactoring work, in many projects, results in pleasant and nice to read code.
Or the old code is a mess. People always learn from their mistakes. Sure you might not understand your old code at first glance but give me a few hours and I’ll understand it fine. It is at this point I’ll be saying wow what dumb ass why did I do it this way.
My favorite story is from a friend in college who worked for Hughes Aircraft on some piece of software that was bloated as a piece of shit. He was confident he could do better so he left and wrote something and ended up rewriting it a few times. Eventually sold out and now lives in a nice house on Manhattan Beach. Granted this was probably the smartest guy I have ever personally known but he was adamant you have to rewrite software a few times to get it right.
The quintessential it's easier to talk than listen
immerc · 1 points · Posted at 22:34:07 on April 26, 2018 · (Permalink)
Imagine if every time a construction company wanted to build a bridge across a river, they tried to keep a lot of the existing bridge around and just bolted new stuff onto it.
You'd have some wood beams, some stone structure, some suspension towers with some iron chains attaching to certain parts of the structure, and some steel cables, some concrete to strengthen certain sections, and so-on.
I think even someone who isn't a civil engineer would see that that would be crazy.
I consider myself well versed in reading code regardless of the scale of the codebase. How do you present that skill in your resume/interview? Especially considering the majority of interviews focus on arguably stupid shit that has no real application to how they actually code.
Fuck you! But yes your right. My first plan starting a new job where I was the only developer was to rewrite everything in my style. They didn't let me, I got pissed and it's kinda working out. I'm a data developer so I planned on translating and documenting the business rules, assigning an owner and getting shit up to vest practice. Instead I spend every day, all day reverse engineering code to see what the fuck caused the problem for the fucking individual report they are running and the fix will break something else they won't run for a few weeks so they won't make the connection. Fuck i hate it and I'm slowly fixing it but I'm still not sure I won't throw in the towel before it's done. You can only put your job on the line so many times with the pretense "what your asking for is impossible with the tools I have" so then they try, fail and you get to do what you want. It's killing me, I've picked up smoking and drinking has increased. One more, fuck you financial industry for using 1980s tech but demand 22nd century accuracy and speed.
I very much experience the exact opposite of this "fundamental law". I can read several programming languages that I could never hope to write functioning software in.
[deleted] · 1 points · Posted at 00:23:19 on April 27, 2018 · (Permalink)
So how do you know the new code will cover the functionality of the old code if the programmer can't read the old code?
Occasionally I might try to rewrite this type code anyways with the intent of tossing the rewrite anyways. Sometimes you can learn about difficult old code by trying and failing yourself anyways.
Can you describe the manner at which you approach that
[deleted] · 1 points · Posted at 05:50:24 on April 27, 2018 · (Permalink)
Good friend of mine always calls code bad when he is reading it. He has switched shops so many times and always somehow got a project approved to rewrite something. After a few years quit because the code his coworkers wrote on his rewrite is so bad and they will just repeat the problem with the legacy codebase. He has done this three times already since I've known him.
I never managed to make him realize what the real problem is. I've read his hobby projects and I do think it is fine to overengineer for the sake of it. His code is like some wicked architect/oop pattern smoothie with the most dense writing style I've seen used unironically. Also everything has to be an object. Nothing can be just a simple data structure or function...
P.S.: He has critized my own code and I've learned a lot from it. He really does know his stuff. With great power...
I have a different reason and it's not because I can't comprehend it. In our Sass files, there are about 6 !important tags per file. The product has about 600 Sass files, if not more. Vendor components have been edited. HTML structure is so unstable it's a fucking miracle we didn't get complaints yet.
Sometimes, there's a perfectly good reason to start over.
Shouldn't that make code maintenance a costlier service than code creation ?
[deleted] · 1 points · Posted at 11:05:34 on April 27, 2018 · (Permalink)
The real REAL reason is that many companies take the lowest bidder or hand down a timeframe created by non-programmers. This creates the framework to write bad code as there’s no incentive/resources/time to do thorough architecture, testing, documentation, refactoring, etc.
So you are either the person they hired for too little, the person they are forcing to do the work in too little time, or the person who comes in after the “clean up the mess” from one of the first two.
I appreciate that, yes, the above is true. But it is a byproduct of competing in a marketplace where the actual cost of good code isn’t understood.
We are the ones that make code more difficult to read, well writen code is like reading a story but for that you have to use some clean code rules
wjcott · 1 points · Posted at 13:18:50 on April 27, 2018 · (Permalink)
The only time I have ever completely scrapped project code is when the structure/logic was so off base that it would take more effort to fix than to rewrite from scratch. The project in question had passed through the hands of two consecutive college interns and had not been given the proper oversight.
There are several big problems that contribute to the codebase being a mess, or perceived as such.
The lack of proper modules in popular programming languages; proper modules are necessary for controlling complexity.
eg C, C++, PHP, and until relatively recently JavaScript.
Related, the ability to make Abstract Data Types [and, IMO, modules] properly generic is rather anemic in most 'popular' programming languages.
(Generics, for example, not able to have subprograms, values, and other generics as formal parameters.)
The lack of valuation of design.
(eg How many "codathon" events are there? How many "designathon"?)
The lack of valuation [and/or dissemination] of the knowledge of the design.
(eg Poor onboarding processes with little to no training; this is tightly related to the more and more common "corporate culture" which is embodied by the term "Human Resources" and views employees as replaceable cogs.)
Riael · 1 points · Posted at 21:13:15 on April 27, 2018 · (Permalink)
fundamental law of programming: It’s harder to read code than to write it.
Can't confirm, was in a piscine at Ecolé 42 and after 30 hours of no sleep people would come to me asking to fix their sastantua and reading their code and debugging it was way easier than doing it myself.
Funny little story but in my sophomore year programming class I was lazy as hell and could easily read what basic stuff I had there meant. The catch 22? Most of our assignments were kinda the same but with different variations on the program and concept usually involving a new thing you just learned. As a result I literally just copy and pasted the previous assignment and redesigned the webpage and retitled existing code or added new code in but in the case a line was unused, I just kept it in there all the same. I would continue copying each previous assignment over and over until it got to the point I had pieces of code from like 6 assignments ago in the most recent thing.
But hey I can't complain. It worked, I passed, and it saved me a lot of time to myself to play Line Rider or The Last Stand on Armour Games.com with my friends. Shit was lit.
No such law exists.
The only reason to throw away code written by someone else is because the majority of these situations have something in common: the code is poorly documented if at all.
It's pretty hard for people -not only programmers- to get into the mindset of someone else's way of thinking, much alone algorithmic though. I have maintained projects with thousands lines of code (written with ancient programming languages (RTL/2) on VMS systems ) that simply would not be possible without the accompanying documentation set of each module. And the option to throw away that code just was not there for us.
frezz · 1 points · Posted at 14:56:57 on April 29, 2018 · (Permalink)
I don't necessarily agree with this, I think his best point is the point that you are giving your competitors 3 years headway while you don't actually ship any new features.
Most of his points are okay if these are the only problems with the code base, i.e. if you had a two pages function with variables called 'FuckedX', variables starting with m_, then changing midway through, the system was architected in such a poor way, refactoring it is almost the same as rewriting it, except you have to work with your legacy code base.
I also completely disagree with the point that you're throwing knowledge away. If you are rewriting your code base you should be doing it on the pretense that you will architect it in a way that will solve many of your major problems that your original system faced, except you won't have a bunch of conditionals in a two page function to do it.
Usually companies rewrite when you are doing so many things wrong in so many places that the combined effort of resolving these issues is less than simply rewriting from scratch, or your system is doing something fundamentally wrong like having data-loss issues or syncing across clients incorrectly.
Honestly IDE's just suggesting to # explanations could be a way to bump up "readability". Really you could up it yourself by taking more notes in the code. I'm also a novice so I'm not sure if that's frowned upon for some reason.
Here's the reason I like starting over from scratch when I'm programming: It's because a few times when writing my own programs I get stuck, and then when I come back later and start over from scratch I get unstuck or am able to complete the program... at least some of the time. So maybe programmers working on large projects where most of the codebase is not their own prefer to start over from scratch because even on their own smaller projects it seems to help them make progress.
iodian · 1 points · Posted at 15:02:17 on April 26, 2018 · (Permalink)
Wrong. We want to rewrite code because the use case the old codes no longer exists and we want to adapt the code to the ever changing use cases.
The article was written in 2000. It's ancient in today's internet standards...
I will vouch that it is definitely harder to read code than write it though.
ntrid · 1 points · Posted at 18:43:23 on April 26, 2018 · (Permalink)
This is why I despise rust. Not because it is a bad language. Because people designing rust had every chance to make a readable syntax and yet they opted for syntax full of voodoo magic just like c++ is. No one cares about code readability unfortunately.
Mya__ · 1 points · Posted at 21:20:00 on April 26, 2018 · (Permalink)
Or maybe as you learn new and better ways to do things you want to bring your new understandings to your old work that can be improved?
Hi guys,
all the problems about starting a new project (code not easy to understand, differents programming languages, lose time for a boring work, difficulty on working in a team of dev) are daily problems for freelancers or for who working in companies.
For this, we created a tool that allows developers to easily create the scaffolding for your projects (and a fully working prototype), in many programming languages, with a source code completely customizable, without writing a line of code, easy to understand and forever free for developers.
In 2018 is so strange to spend your precious time doing something that can be automatized.
Our mission is to help you to work, reducing your development time that can be spent on the custom part of your new projects!
Our mantra is: "Do not reinvent the wheel!"
Try it for free on www.skaffolder.com and if you want, give us a feedback :)
That's complete bullshit. When you're working on a codebase written by underpaid Pakistanis or Romanian interns, the old code is a mess, no arguing about that.
lukeautry · 2376 points · Posted at 14:07:58 on April 26, 2018 · (Permalink)
I think most programmers work in a similar way: imagine a problem, then decompose the problem into its constituent parts and attack those simpler, isolated problems.
The problem with a large codebase is that no one, not even the person that wrote all of it can fit the solution in their working memory. The tendency of programmers (who generally underestimate complexity) is to say: wait a minute, this problem doesn't require 10 million LOC, I could easily solve this problem in 250 lines of elegant Haskell.
There are situations where the legacy codebase is completely unsalvagable, but I think more often than not it's throwing the baby out with the bath water, except the baby is an engine that, while flawed, is generating business value.
nickiter · 718 points · Posted at 18:27:23 on April 26, 2018 · (Permalink)
I think this is what a lot of people - even some coders - don't understand about enterprise-grade software systems.
Quite literally no one knows everything about any such system - you have to take a systems approach, design for modularity, document like a graphomaniac, and expect constant rework.
occams--chainsaw · 715 points · Posted at 20:57:56 on April 26, 2018 · (Permalink)
Unfortunately, a significant number of those enterprise systems weren't designed for modularity, have little to no documentation, and receive almost no rework to minimize debt.
btreecat · 500 points · Posted at 21:25:16 on April 26, 2018 · (Permalink)
This coder enterprises
[deleted] · 45 points · Posted at 23:11:38 on April 26, 2018 · (Permalink)
[deleted]
spockspeare · 14 points · Posted at 00:57:31 on April 27, 2018 · (Permalink)
Rest his soul.
pranaykotapi · 5 points · Posted at 09:22:57 on April 27, 2018 · (Permalink)
this guy drives a car where the doors open like "this" and not like "this"
[deleted] · 2 points · Posted at 09:32:57 on April 27, 2018 · (Permalink)
[deleted]
pranaykotapi · 3 points · Posted at 09:44:10 on April 27, 2018 · (Permalink)
https://i.ytimg.com/vi/0oV4IVy8tvE/maxresdefault.jpg
MasterKongQiu · 1 points · Posted at 21:58:54 on May 17, 2018 · (Permalink)
Not if you round down. If you round down, I have 0 billion.
crustalmighty · 2 points · Posted at 03:06:22 on April 27, 2018 · (Permalink)
This male human engages in sexual intercourse.
TheTygerWorks · 3 points · Posted at 12:55:57 on April 27, 2018 · (Permalink)
I'm living in one of those worlds now. Fortunately I get to build new systems right now and not work on maintenance of current ones, but the last thing I worked on was an impressive monstrosity.
The best part was that the project I was working on was only scoped to fix compatibility issues, so we had to re-create interface bugs that were fixed when we fixed the compatibility, because it would break the user flow for end users.
massivewurstel · 76 points · Posted at 21:13:01 on April 26, 2018 · (Permalink)
The comment you replied to wasn't saying how the systems should be, it's what you have to do when you encounter such a system. No modularity? Start breaking it into submodules. No documentation? Write some (while you explore the system yourself). No time to rework? Communicate the urgency of it to the manager. That's actually what the best of the best programmers do (I'm not one but I've seen some of them in action). This is where all the hard work is, not coming up with a new solution/framework/system every time pretending you're Linus Torwalds.
[deleted] · 68 points · Posted at 21:23:54 on April 26, 2018 · (Permalink)
[deleted]
[deleted] · 145 points · Posted at 23:15:59 on April 26, 2018 · (Permalink)
[removed]
yeahbutbut · 3 points · Posted at 20:13:19 on April 27, 2018 · (Permalink)
If you're skeptical of this plan, so was I for about 5 years. Best decision of my life.
Logseman · 2 points · Posted at 09:23:51 on April 28, 2018 · (Permalink)
It's a good thing you can choose another high-paying job. Most coders in other countries don't have one in the first place, and switching jobs means months of not being paid only to land another job with mediocre pay.
Mourningblade · 25 points · Posted at 11:46:55 on April 27, 2018 · (Permalink)
You need to think like the person who writes the checks, not like the person who just writes the code.
Step 1: Think about why companies pay for your time:
You don't want to break up the code because it's a best practice. No one pays for best practices. You want to break up code because it will be easier to change and easier to find bugs.
Step 2: Find a section of the code (a file or set of files) that is both frequently changed and hard to change - or find a section that is both prone to errors and difficult to debug.
Step 3: quantify step 2. You should be able to say something like:
"Over the past 6 months, we've had to change X Y times. I estimate that the complexity of X has cost us Z days of additional time (% of feature development time). We are very likely to keep modifying this code. If I get H hours, I can eliminate this extra time."
Another pitch you can make is to correlate changes to bugs, like:
"Over the past six months, we've changed X Y times to add features. This caused B bugs costing D days to resolve. F upcoming features will require modifying the file again. If I'm given H hours, I think I can reduce the cost of bugs per change by % - saving us S hours of debugging over the next 6 months."
Have a way to measure this that you will repeat over the six months after modifying the code. It doesn't have to be incontrovertible, just probable - people who write checks are used to working with probable. Keep in mind that the less certainty your measurement has, the bigger your gain has to be (would you pay $10 for a 50% shot at winning $20? No. How about winning $50?).
Step 4: pitch it, then put your money where your mouth is. Make the changes, watch the cost reduce - or not. I recommend providing follow-up reports at 1 month, 3 months, and 6 months comparing projections to actual.
If you aren't confident that you can produce these outcomes, then you should not receive the time to do them. If you can produce these savings, then you should receive the time.
Note: there are good reasons why you still might not immediately get the time. If the company has to produce X changes within Y time and it won't be able to do so while also paying for your changes, then you won't receive that time. You can offer to reduce the cost by doing your refactoring as you make the next N changes, adding H hours to each change but still getting most of the results.
Higher-ups are frequently familiar with the fact that your changes are taking longer and longer and your bug rate is going up (often painfully aware, actually). If you can give them a why, what to do about it, and a way to see that you're correct or wrong quickly without having to pay for the full rework, you bring actionable knowledge. That's how you get your seat at the big table.
Source: engineering manager. I've been a having these conversations for a few years now.
pdp10 · 9 points · Posted at 21:51:39 on April 27, 2018 · (Permalink)
You have excellent points and I upvoted this post.
However, I feel the approach isn't sufficiently agile for a lot of shops, and the idea of making (what is nearly) a full-blown sales presentation in order to do my job fills me with weariness. It seems to require exceptional ability to plan ahead and to estimate, both of which are considered very difficult in the real world.
Only do this when you've been actively prevented from fixing something. Otherwise, the default posture should be to ask forgiveness, not permission, when it comes to your codebase. The same principle can be applied to operational change control, under proper conditions.
Mourningblade · 10 points · Posted at 03:00:06 on April 28, 2018 · (Permalink)
Absolutely yes.
Honestly, the best way to improve code is with every change. Every change should make that section of code a little easier to change next time.
Most of the time when people ask for refactoring time, it's a major refactoring. Most major, non-incremental refactoring is misguided.
The method I provided is best when you want to change how your company works - to convince people to that your new standard should be...well, the standard. It also works when you're prevented from taking time to refactor charges.
Besides that, though, it's a good skill to be able to reason in this way, to communicate in this way, and make promises in this way. I'd say the whole presentation is about 3 slides or a short email (problem w/ data, why the problem exists, proposed experiment). Reasoning about development in terms of business needs rather than programming best practices.
Of course, scale is everything. I've worked on two-person teams where it'd be as simple as "I tried this in my recent patch, what do you think?" I've worked on 100 person distributed teams that require a bit more communication overhead.
feenuxx · 15 points · Posted at 00:19:57 on April 27, 2018 · (Permalink)
Lying about it causing issues has been the course I’ve taken in the past. It’s a noble lie.
anon_cowherd · -1 points · Posted at 17:52:39 on April 27, 2018 · (Permalink)
Also: fraud.
feenuxx · 4 points · Posted at 17:53:06 on April 27, 2018 · (Permalink)
Sosumi
massivewurstel · 20 points · Posted at 21:36:55 on April 26, 2018 · (Permalink)
It's the hard part because we as programmers are usually not so good at working people. I had situations when I tried to do my best and failed, sometimes it works after some time and constant reminders. It's just I believe we are not here to deal with the shiny cool stuff, we are here to deal with all this crap for the most part. The fact that a person can leave something better after themselves than what they took over speaks a lot, and often they are not enabled by their company at all.
Of course there are crappy companies, and sometimes leaving is the only option. But in my experience 100% hopeless employers in this regard are less ubiquitous than it seems.
CommonMisspellingBot · -13 points · Posted at 21:36:59 on April 26, 2018 · (Permalink)
Hey, massivewurstel, just a quick heads-up:
beleive is actually spelled believe. You can remember it by i before e.
Have a nice day!
The parent commenter can reply with 'delete' to delete this comment.
Nyefan · 9 points · Posted at 21:43:11 on April 26, 2018 · (Permalink)
God what a useless bot - it can't even handle the classics.
wolfman1911 · 3 points · Posted at 22:49:53 on April 26, 2018 · (Permalink)
This is my first time hearing the bit about being pronounced 'ay'.
majelix_ · 6 points · Posted at 00:57:29 on April 27, 2018 · (Permalink)
Proactive sprint planning and honestly pessimistic estimates. The "sandbagging curmudgeon" during planning tends to be "the only team member that nailed their tasks" in the retro.
Or, you know, law of two feet.
berthoogveer · 1 points · Posted at 05:50:03 on May 7, 2018 · (Permalink)
What is the law of two feet?
majelix_ · 1 points · Posted at 19:38:59 on May 10, 2018 · (Permalink)
You've got two feet, and can use them to walk away (ie, quit). Probably a last resort, although this is a pretty grand time for employees in our industry.
berthoogveer · 1 points · Posted at 20:01:05 on May 10, 2018 · (Permalink)
Haha ok thanks for explaining :)
prof_hobart · 7 points · Posted at 06:12:09 on April 27, 2018 · (Permalink)
Why should they care? And by that, I don't mean that they should't - I mean understand why it would be important to the people paying for it, and that gives you the tools to convince them.
Did the last feature take 3 times as long as it should have because you didn't understand the code? Have you spent half your time in the past 6 months dealing with production incidents because the code is unstable and the logs aren't good enough?
If your employer has any interest in how long it'll take to deliver the next feature, they'll be interested in ways to make that delivery (and the ones after that) quicker.
"I want to document the code and move a bunch of files around" is quite rightly going to be met with blank states and a lecture about delivering value.
"I want to halve the time it takes between you coming up with the next killer feature and that feature being in the hands of the user" is going to get them much more interested.
gimpwiz · 6 points · Posted at 04:32:01 on April 27, 2018 · (Permalink)
I don't ask. I just do it.
What're they going to do about it? Fire me? I would love a three or six month vacation. But I know that it costs >$100k to hire someone, on average, into a position like mine, for companies where I live. Firing isn't cheap either. Letting your employee spend some time here and there improving code is way cheaper, even if you wish they spent 100% of their time on features.
Of course the truth for me is that my boss is a technical person, and my boss's boss, and my boss's boss's boss, and so on. They all understand the value of spending a bit of time improving things under the hood, and wouldn't think to hassle me about it, so it's a moot point.
stormblooper · 2 points · Posted at 12:41:07 on April 27, 2018 · (Permalink)
One approach is just to improve things as you go. You don't have to ask permission to write a for loop, right? Similarly, as developers, we don't need to ask permission to pay down technical debt. We just do it as part of our job. If you're being micromanaged to the point where this isn't possible, well, look elsewhere.
Also, if you're working 60 hours a week...please stop doing that.
pdp10 · 1 points · Posted at 22:01:24 on April 27, 2018 · (Permalink)
I generally agree, but it should be noted that there are houses where official policy is to keep diffs minimal. Either for understandable but possibly misguided reasons, or because of less understandable diktat from principal.
confusedpublic · 1 points · Posted at 07:34:35 on April 28, 2018 · (Permalink)
Put it in return on investment terms? By spending 10 hours fixing this now, you won't have to spend 20-30 fixing it later. It's cheaper in the long run to fix things now than to lose money while trying to fix them later. Helps if you can document bugs and downtime due to these issues.
sroasa · 3 points · Posted at 00:00:18 on April 27, 2018 · (Permalink)
AKA the big ball of mud development pattern.
leixiaotie · 3 points · Posted at 03:56:34 on April 27, 2018 · (Permalink)
I think you haven't worked in enterprise-y environment or similar. The legacy code is one big of a mess, and to rework that into submodules need, well, rewrite. It may be so big that it takes hours to days to weeks even to modularize the smallest subsystem (oh man the jargon). And managers don't like that. They love small man-hours tasks to do some enhancement, no matter how you hack them.
And what's worse is, there are no or useless documentation. I couldn't care less about technical documentation, at least you can read code. But they also don't have business documentation, and any person in charge doesn't know any of the business process. They rely on how the system work right now, so it's hard to do even the slightest modification, because the risk is really high.
And making the management agreeing to do a rewrite may be beneficial, that they can start to define the business flow and test cases, managers start holding responsibilities for business flow, testing and bug fixing timeline will be longer, which you won't get any in normal flow.
z500 · 1 points · Posted at 14:00:41 on June 2, 2018 · (Permalink)
As if we had the time to make the codebase less shit, rather than just shoving features out the door.
[deleted] · -3 points · Posted at 21:13:16 on April 26, 2018 · (Permalink)
[deleted]
occams--chainsaw · 3 points · Posted at 22:55:05 on April 26, 2018 · (Permalink)
Hey, CommonMisspellingBot, just a quick heads-up: comming is actually spelled cumming. You can remember it by u cum. Have a nice day!
The parent commenter can reply with 'delete' to delete this comment.
IrishPrime · 12 points · Posted at 23:02:04 on April 26, 2018 · (Permalink)
The only code I've ever worked on which was well documented was code which was documented or written after I started the job.
stewartm0205 · 8 points · Posted at 23:35:31 on April 26, 2018 · (Permalink)
We were forced to burn our documentation. Design and program design was taking too long. So our director decided that it all had to go. He figured if we went directly to coding we could save 70% of the time.
metis2 · 1 points · Posted at 06:28:13 on April 27, 2018 · (Permalink)
Also, I've seen enough sales men offer handing over code as part of a sale knowing full well that code was worthless with out the original programer
pythonicus · 5 points · Posted at 22:26:05 on April 26, 2018 · (Permalink)
Because many companies and many developers don't understand how to cleanly separate the domain from the infrastructure.
nickiter · 2 points · Posted at 22:11:20 on April 26, 2018 · (Permalink)
Harsh truths.
GBACHO · 2 points · Posted at 06:13:33 on April 27, 2018 · (Permalink)
Documentation is also another bit that needs to be parsed. It may be out of date with business requirements or code. There are definitely situations where documentation is a hindrance. The truth is always in the code. Documentation is what someone wanted to truth to be
Droid2Win · 1 points · Posted at 23:52:34 on April 26, 2018 · (Permalink)
So true. My company, our application was mostly written by an offshore firm (I was hired as a part of the process of moving development back to the US). The code is partly modular, but mostly tightly coupled, and in some places is a complete mess. Most of it is maintainable, but there are pieces of it where the codebase is so horrible most devs on staff are afraid to touch it. When I started I was super cocky and made it my mission to take on all the challenges there... Let's just say I no longer do that anymore. Too painful to deal with.
Our general approach is maintain as best we can, but periodically we find time to do a complete rewrite of certain pieces of the app. Not the whole thing, but parts of it that don't just have bad code but actually work very poorly, where it is worth the effort.
spockspeare · 1 points · Posted at 00:57:17 on April 27, 2018 · (Permalink)
Time to money, baybee!
bubuopapa · 1 points · Posted at 10:42:58 on April 27, 2018 · (Permalink)
Exactly this - devs hate other devs and other devs code for exactly this reason - it is super hard to read and understand all the brainfarts that other dev had while writing the code. Lack of documentation, lack of proof that the code works and that it does all the things that it should do, it all drives us to just dump all the code in toilet, because it would take longer to understand all the mess than to write your own code.
[deleted] · 1 points · Posted at 10:59:29 on April 27, 2018 · (Permalink)
Which is why the real problem with software is just that you get what you pay for.
Enterprise software is built for enterprises that don’t want to pay for testing, documentation, system architecture, refactoring....
Good_Guy_Engineer · 1 points · Posted at 15:13:15 on June 19, 2018 · (Permalink)
We must work in the same office :)
ObstreperousCanadian · 1 points · Posted at 00:30:04 on April 27, 2018 · (Permalink)
JD Edwards says hello!
appropriateinside · 50 points · Posted at 21:13:25 on April 26, 2018 · (Permalink)
Serious question, how do you document these systems? What do you document? Documentation is my hardest area, I don't know what the next dev will want to know.
[deleted] · 85 points · Posted at 21:29:32 on April 26, 2018 · (Permalink)
Explain the purpose of each class/method. Walk them through how your code works. Explain why you choose the implementation that you did perhaps by listing pros/cons of the alternatives. Try to break large methods into smaller well named ones. Name variables clearly, avoid excessively long expressions, avoid obscure ways of doing things(like the xor swap for example). Readability is always preferable to a few saved operations, so pick readability when faced with this choice. Try to keep code modular, it's easier to understand that way. Methods/classes should "do one thing and do it well".
appropriateinside · 49 points · Posted at 21:55:23 on April 26, 2018 · (Permalink)
I should have been more clear, what I currently do:
I'm good at documenting things piece by piece, methods, variables. I'm bad at external documentation describing how these individual pieces work together to do something. I know how they work, I can write it out, but I always end up writing a novel instead of something easy to digest.
candybrie · 18 points · Posted at 22:02:02 on April 26, 2018 · (Permalink)
Maybe what you're working on deserves a novel. If it's clearly written and everything spelled out, reading that is significantly easier and more helpful than terse documentation.
It's kind of like dissertations versus conference papers - I way rather read a dissertation where they took all the room to explain every last detail than a conference paper trying to pack all their contributions in a small page limit even though the dissertation is about 10x longer.
wslee00 · 1 points · Posted at 12:01:39 on April 27, 2018 · (Permalink)
Majority of folks dont want to read a tome when it comes to documentation. If it looks too big to digest they will probably not read it at all. The code should be self documenting via clear class and method names. That way when you change code there is no documentation that needs to be updated. The only time comments should be necessary is explaining WHY something was done. Otherwise the "what" of the code should be able to be followed from the code itself.
In terms of documentation I think class relationships would be a good candidate, I.e. A diagram showing said relationships in an easily digestible format
candybrie · 3 points · Posted at 12:47:37 on April 27, 2018 · (Permalink)
Even good self documenting code is harder to read than someone's explaination of it. Thinking it's not is how we end up with so little documentation and everyone preferring to start over. If every codebase I needed to modify/maintain came with a nice tome, I'd be ecstatic. Especially if it was neatly organized, had a nice introduction chapter, and then chapters for each subsystem. No one is gonna read it cover to cover, but going to the relevant part and having everything I need to know right there? So helpful.
As for why? Class diagrams to me do not tell me at all what the person was thinking when they did X. I don't see how they help answer why. Class diagrams are super useful for what exists but you said this documentation should only answer why - which is usually done a lot better in writing in my experience.
bhat · 11 points · Posted at 22:10:24 on April 26, 2018 · (Permalink)
The most powerful concept in computing is abstraction: being able to hide the complexity of a subsystem or layer so that it's easier to think about and work with.
So maybe the abstraction is leaky (details that are supposed to be hidden need to be known outside the subsystem), or else the boundaries between subsystems aren't ideal.
taresp · 1 points · Posted at 14:57:39 on April 27, 2018 · (Permalink)
Provided it's done at the right granularity. A lot of times too much abstractions makes some fairly simple things hard to think about and work with. You can easily take a problem that originally fit in your memory and blow it up with abstractions to the point where there might even be less code, it might be more modular and flexible, but you can't see it as a whole.
Kind of like the idea that early optimization is the root of all evil I'd be tempted to say that early abstraction is almost as bad, but I guess it's really on a case by case basis.
daperson1 · 4 points · Posted at 02:09:35 on April 27, 2018 · (Permalink)
There are really two audiences for your documentation:
The former do not want to know the details of how it works. They want to know how to use it, the inputs it can cope with, how it handles edge cases, how it performs, and when it is appropriate to use it.
The latter are the people who need the tiny internal details.
A common strategy is to put the documentation for "users" in doccomments (which eventually end up in generated reference documentation, or a readme), and documentation for "modifiers" in the implementation itself. You might end up with an explanation of usage as the doccomment, and the function implementation starting with a largeish comment explaining how a fancy data structure works or something
The high-level goal is to allow people using your code to solve their problems without having to think through all the details of solving the problem your code solves. If your documentation forces the user to read their way through the thought process needed to solve that target problem, you've failed to abstract properly.
marnues · 2 points · Posted at 22:52:35 on April 26, 2018 · (Permalink)
I've personally gotten much better at architectural diagrams. I always start there. If I can't conceptualize a simple diagram, then I haven't broken the problem down well enough yet.
Then my documentation starts with the diagram and the contracts ingress/egress. Pick a piece of the diagram and it should point at more specific documentation. Some times there's further diagrams, but eventually you'll get to API documentation.
I think the most critical thing is that code comments are a last resort. The primary audience for my documentation is the Product Owner and Consumers. I tend to only free hand comment on code when I can't reasonably fit the documentation into a higher layer.
chreekat · 1 points · Posted at 03:11:20 on April 27, 2018 · (Permalink)
You say you write a novel, and the thing is, I think that's the right track. I believe narrative descriptions of systems are a critical piece of sharing knowledge. The part you may be getting stuck on is editing: the real meat of the work of a writer. Chances are your "novel" is full of great insights and useful data, and if you could develop a clear strategy for laying it all out, and make it pleasant to read, you'd end up with something valuable.
I was just recently rereading parts of "Writing with Style", a short, excellent book on the art of expository writing. Maybe check that out and see if any of it resonates.
vcarl · 1 points · Posted at 03:14:22 on April 27, 2018 · (Permalink)
One point that I haven't seen in the replies: sometimes writing is the wrong medium. If you've written a novel, could it be communicated as a diagram, or a cartoon, or a talk?
There are also ways to improve your technical writing skills, which is definitely a skill in itself. Know your audience and what they hope to get out of it. Remove fluff and filler, give different levels of explanations at different points of the documentation. If there were a simple answer to "how do I write better documentation?" then there wouldn't be so much terrible documentation. I love this tweet from Kent C Dodds about how to write a good readme: https://twitter.com/kentcdodds/status/976813153647394816
daperson1 · 1 points · Posted at 02:03:24 on April 27, 2018 · (Permalink)
Just to add: something people often fail to do is to specify the goals and specific non-goals of a particular class or function. This can lead to someone later "fixing" it by adding defensive checks for something that you really wanted to assume as a precondition, or by mutating what a class represents in a "useful" but ultimately problematic way.
It's also worth learning in what situations "tradeoffs" for readability vs. speed actually aren't tradeoffs because the optimiser is doing it for you. I've met many people who vastly underestimate the capability of a modern compiler, and end up believing they're making a speed/readability tradeoff in situations where they're not: both options end up as the same instructions. Common instances of this include division by compile-time constants (which some people like to explicitly replace with shifts or fixed point reciprocal multiplies) or function calls (which people routinely seem to forget get inlined).
Obviously, if you're using a scripting language or something this doesn't apply (modulo JIT, if present), but if you're using a scripting language and you care about micro-optimisations you probably shouldn't be using a scripting language (or you probably should stop caring)
macrocephalic · 1 points · Posted at 03:37:12 on April 27, 2018 · (Permalink)
Exactly this. Too many people think they're playing code golf at work. The problem with that is that, as this article mentions, reading code is harder than writing it. Another article, I think by Joel, also explains that debugging code is harder than writing it. If you write the most complex code that you know how to, then you won't have the expertise to debug it when it breaks (and it will).
prof_hobart · 1 points · Posted at 06:19:13 on April 27, 2018 · (Permalink)
In most cases, the method name should tell you that. updateAccountBalance() should be updating the accountBalance and you shouldn't need comments for that. They'll at best be redundant and a waste of effort to produce, and at worst they'll be or become wrong.
Comments are best used sparingly - tell us the thing that the coder can't obviously figure out from the code - that you picked this particular sorting algorithm because the distribution of key fields is skewed in some odd way; that you add 2 pixels and then take 1 off because of some obscure bug in the version of IE that your company uses in the Italian office; that you've no idea why this works, but it does and everyone who's ever tried to refactor it has brought down the server etc.
nickiter · 19 points · Posted at 22:10:23 on April 26, 2018 · (Permalink)
Hard to say precisely without knowing what you're working on, but for my work, I LIKE all of the below, though I usually have to settle for just most of it due to customer constraints or what have you.
People tend to over-emphasize comments, IMO, not that you shouldn't use them, but they should be helpful detail backing up higher level conceptual documentation that helps the next devs find the files or code blocks they need to look at in the first place.
IrishPrime · 3 points · Posted at 23:07:27 on April 26, 2018 · (Permalink)
These are great suggestions. Once I'm in the code, unless it's a real mess, I can figure out what a function does and what it returns and what it depends on. Finding my way to that first function, however, can be an ordeal.
Been making great use of our internal wiki lately, and it's a game changer.
OneWingedShark · 2 points · Posted at 20:25:46 on April 27, 2018 · (Permalink)
Great ideas; another I would suggest:
For any medium-large to large project, employ an actual technical writer to produce usable documentation.
(Also, never, NEVER use Confluence or similar as 'documentation'.)
ace1010 · 1 points · Posted at 06:54:26 on April 28, 2018 · (Permalink)
What's so bad about using confluence?
OneWingedShark · 2 points · Posted at 21:00:52 on April 28, 2018 · (Permalink)
Using Confluence for documentation means, invariably, that the documentation grows into a horrid mess. Wikis can be used well [for documentation], but Confluence?
Part of the "horrid mess" phenomena is, I think, that there's a pretty big difference between the technical writer mindset and the developer mindset, and Confluence is often embraced [in part] to allow management to push documentation on the developers... except that with all the time-pressures they often miss out on the needed "context-switch".
Overunderrated · 1 points · Posted at 10:05:02 on April 27, 2018 · (Permalink)
Example of what you're talking about?
nickiter · 1 points · Posted at 13:29:24 on April 27, 2018 · (Permalink)
https://c4model.com/#coreDiagrams
[deleted] · 1 points · Posted at 23:29:00 on April 27, 2018 · (Permalink)
[deleted]
nickiter · 1 points · Posted at 01:44:34 on April 28, 2018 · (Permalink)
Well, I'm the project/program manager, so I get to make suggestions. ;-)
xcdesz · 4 points · Posted at 04:04:48 on April 27, 2018 · (Permalink)
Take a look at the README files on some popular GitHub projects and copy what they are doing. README's and code/api documentation are really the only things that are useful to other developers. Put down everything you know -- it's a README -- you won't find a project manager nit-picking your words for political reasons.
Don't use anything fancier than a text editor to document. Anything that goes into a Word Document or Powerpoint will often wind up in Sharepoint and never be seen again.
spockspeare · 3 points · Posted at 00:58:27 on April 27, 2018 · (Permalink)
He'll want to know
a) what does it do,
b) how does it do it, and,
c) what the fuck were you thinking?
What he really doesn't want to know is the history of the development. Seriously, stop jacking off in the webpage. Tell me what your package is, not who made it or why. Put those things four layers deep in the "about our egos" page.
appropriateinside · 2 points · Posted at 03:02:47 on April 27, 2018 · (Permalink)
This is really internal docs, not external. They would be used by a future maintainer.
AskMoreQuestionsOk · 2 points · Posted at 23:06:36 on April 26, 2018 · (Permalink)
You’ll have architecture documents that describe how everything works at a high level along with the audience and use cases for a system and then functional specifications for particular features. There may be testing specs also that describe what is to be tested and how. If you hand those specs to a developer, they should be able to implement what is described. A technical writer may also use these documents to describe APIs, limitations, requirements and even usage examples to customers. When you see a public API - it has probably been documented in a specification somewhere even if it is a code generated API.
So it’s safe to say that several audiences will be looking at the documents. Data structures, APIs, unusual memory management, multi-thread, multiprocessor issues should be noted and explained. Limitations, dependencies on other features and restrictions should also be clearly noted. Large enterprises may have standards for naming and file structure, prefixes and the like. Those need to be noted somewhere and if the structure is non standard that too should really be described. If there are performance requirements, hardware or character set requirements, those need to be in the document.
The bottom line is, the more detailed accurate the document is, the easier it is to implement and the easier it is to debug if you are new to the code. The spec drives the implementation - not the other way around. You aren’t documenting a feature after you have implemented it. There are too many people involved to code sling like that.
DaveDashFTW · 1 points · Posted at 01:07:11 on April 27, 2018 · (Permalink)
This is amusing to me.
I help the worlds largest (non-tech) companies to do exactly the opposite of your post, because they’re all screaming out for it.
I come from the Pivotal/ThoughtWorks etc school of thought where SRS documents and so forth are basically waste.
Not trying to create an argument here btw, just offering a different perspective.
AskMoreQuestionsOk · 1 points · Posted at 02:50:59 on April 27, 2018 · (Permalink)
Well there’s more than one way to do things, that’s for sure. But if you’re rolling out documentation to customers and other engineers, if you don’t have some kind of document, all that know how is trapped in an engineers’ head - how is knowledge debated and transferred efficiently and accurately to people not in the room? My experience is that these documents are quite helpful as it represents the settled architecture and implementation and can be read by normal people. Now maybe the form is different for others- a wiki, or whatnot, but that’s just formatting. All documents that aren’t code generated have a problem of rot if the documents aren’t maintained.
I’m sure that there are forms out there that write first and document later, if at all. That doesn’t work well if 2000 engineers downstream are trying to use your code, but is perhaps fine in smaller groups that communicate well.
And I’ve worked with groups with no useful documentation. I didn’t stay there long. The code was just as bad.
I definitely curious as to your philosophy. I have heard of firms that build delicate equipment that have huge documentation requirements to verify it does what it’s supposed to do. Parts for rockets and the like, for example. Way, way, more documentation than I ever had to write. So there’s all kinds of styles.
DaveDashFTW · 2 points · Posted at 07:16:55 on April 27, 2018 · (Permalink)
Basically what I teach my customers is moving more towards a DevOps agile world.
The first step is to start adopting microservices. Start with a new greenfields initiative and leverage Kubernetes (or Service Fabric for .net teams) and architect your application in such a way that it’s small discrete domains.
Once your first few teams get familiar with microservices and orchestrators (which really are the glue that holds everything together), start breaking development teams up into smaller pods that own the full lifecycle of that application. Smaller applications means faster development cycles, less complex documentation, and safer release cycles since there’s not a lot of fear of taking down the entire system with a bug (assuming its architected correctly with circuit breakers etc).
Once your teams are familiar with this concept, start building in a lot of automation and start coding in a more agile way. Develop blue/green or canary testing since you now have the platforms in place to support, leverage automated build tools, abstract away the Ops in DevOps as much as possible.
Now go back and build a facade and start slowly migrating your older applications into this new pattern.
Documentation is still important in this world, but by breaking down code into smaller manageable services is becomes easier and also less critical. High level architecture diagrams and process flow diagrams are still important, but everything else is captured in your epics, features, and backlog. Also the more automation you adopt the more automated documentation you can do, and the quicker you can react to change when your customers demand it, keeping your documentation up to date. Swagger is a great example of this.
I always have a disclaimer though - Agile and DevOps is not suitable for everything and anything. Use the right tool for the job.
boki3141 · 1 points · Posted at 02:40:43 on April 27, 2018 · (Permalink)
I'm in the same boat. And I'm of the understanding that the entire agile philosophy works the opposite of the above post. Doesn't the whole "requirements are king" idea lead to all the problems associated with the customer not really knowing what they want and change being super difficult to implement when it arises?
AskMoreQuestionsOk · 1 points · Posted at 03:36:31 on April 27, 2018 · (Permalink)
Agile is a different approach. But if you have thousands of developers working on a piece of software, you aren’t making complex changes without getting a lot of experts involved - sometimes in multiple time zones and divisions. Agile doesn’t really apply.
Agile does a lot better when the problems are simpler and time frames are a lot shorter and everyone is close by.
DaveDashFTW · 2 points · Posted at 06:57:59 on April 27, 2018 · (Permalink)
For large complex projects this is where micro-services or SOA patterns come into play, which also solve the problem that you’re talking about. Platforms like Kubernetes combined with docker do a lot of the heavy lifting so smaller teams can work in a more agile fashion on large complex systems. This is how the tech giants do it at large scale, and they’ve democratised their orchestrators to make it achievable for the rest of us too.
Agile can and does work on large scales though. One of my customers (a bank) has 7,000 developers working on “more or less agile” with some tweaks.
ThoughtWorks also does agile successfully at a global scale. I don’t work for them but I know how they operate.
The point is really that there is a fundamental gap between the business and the technology that is best bridged by getting something into the hands of the business ASAP. Because wasting too much time on non-development outputs (like a SRS) is effectively a waste of time and money.
And in a lot of cases it’s true. I’ve had customers who insist on the “Big Design Up Front” way before and spend hundreds of thousands of dollars on design and documentation, only for it to change dramatically sometimes before the actual development even begins. A lot can change in six months, especially if you leverage the elasticity of the cloud. Then when the users finally start using the application, and it doesn’t work the way they expect, I’ve seen entire rewrites.
Of course there’s always exceptions - legacy banking systems, medical platforms, safety systems, military systems, etc. Anything that doesn’t really have a user interface, is mission critical to a countries infrastructure, is fairly static, and potentially has a lot of dependencies on a lot of legacy systems, are not usually a good candidate for “full” agile.
p1-o2 · 2 points · Posted at 08:42:49 on April 27, 2018 · (Permalink)
Can confirm. Micro-service architecture for enterprise is where it's at for keeping the concerns of the software loosely coupled. Agile can work well if it's implemented correctly and has the architecture to support it. Documentation doesn't have to be a waste so long as it's well constrained just like the code.
MonokelPinguin · 2 points · Posted at 23:54:35 on April 26, 2018 · (Permalink)
One thing, I really like, when it's documented, is things, that you, as the implementer, had trouble with. The API needs a special value, that isn't directly obvious? You thought carefully how to structure your loop? Those things are invaluable for someone trying to understand the code, as they can only guess, why you did something. Often people document, what the code does, but that should be obvious, when you name your variables, functions and types correctly. When it isn't obvious and you can't refactor, to make it clearly understandable, document it.
This only documents the code, but as applications grow larger, having documentation, that gives you an overview, is pretty important. At a certain point applications become to large to fit in ones head. Documenting the larger modules, where they can be found, how they interact and how their interfaces should be used, reduces the amount of information every developer needs to keep in their head, as they can view other code as a black box, that works as specified (until it doesn't, but that's a different problem).
Also start writing documentation early. None wants to document stuff and often people don't go back to document thing, when they are done making their changes, so get in the habit to document early. Also it can be useful to update/write documentation, when you have to understand a new system/module, as you are in the seat of someone new looking at the code, so you have a better idea, of what needs to be documented and it helps to understand things, when you have to think about, how to explain it to someone else.
sbrick89 · 2 points · Posted at 03:31:17 on April 27, 2018 · (Permalink)
In my experience, best place is in the code. "Handle weird case X because data from system Q does this sometimes per user requirement xyz"
Component documentation in a system / solution folder, but the edge cases should be in the code for future maintenance considerations.
cdarwin · 2 points · Posted at 05:41:40 on April 27, 2018 · (Permalink)
For every hour I spend actually writing software. I spend at least another hour documenting. That includes:
Comments in the software: Comment blocks at the beginning of classes and all methods. Additional comments pepper through the code to provide insight into what the hell something is doing.
Jira Issues: Every line of software and every change is traceable back to a ticket. That ticket can be: a bug, an improvement, or a new feature. A ticket lifecycle:
Git Version Control: We have git rules in place that will not allow any commits unless the commit message is formatted to indicate which Jira issue is being addressed.
Confluence: Is used to plan software releases and coordinate team members
We also maintain several documents:
goomyman · 2 points · Posted at 01:36:56 on April 27, 2018 · (Permalink)
documentation is out of date before you start writing it. Static documentation is only ever necessary for government work or legacy work - like building planes or something that last 30 years and need really really old stuff that wont change by design.
For everything else document your one pagers and initial design to get buy off and money and never look back.
IMO you write documentation for modern fast moving software to get a promotion from management that cares about documentation - the key is to write the documentation outline - that everyone else should follow! - and then document your own stuff that you understand with it.
Sell it to your boss - get a promotion - and then watch everyone else groan that they have to document their stuff or follow some new business process. Meanwhile you look great for being the only service with "proper" documentation.
Be sure to get your promotion before your documentation is out of date and your stuck with your own business process. Let someone else kill your business process while you already got the glory.
PeacefullyFighting · 2 points · Posted at 23:48:38 on April 26, 2018 · (Permalink)
And the users are worse. They describe a problem and expect some sort of answer on the spot. I've never heard of the field your referencing and I don't know where it's sourced from until I look. I get it, it's an error that could cost us millions but I still need to look first and getting my panties in a bunch does nothing but make you feel better because I share your concern. I deal with these problems hourly so no it's nothing new and nothing to get upset about.
The pattern I see is a developer gets a ton of respect in the beginning because they can get shit done super fast but eventually they hit the point your describing and need to start reverse engineering because they didn't document or put any focus on best practice. The president they set puts them in a tough spot and they get driven out of the job. The next developer comes in (and probably got themself into this same spot at a previous company) so they refuse to operate that way. Executives are stuck so they have to give a little more leeway and things start to get done right but there isn't time to fix everything, just what needs repair. Eventually things come to another pressure point and the company hires a consulting firm which results in enough manpower and drive to actually get everything fixed. At this point it's 50/50 if the lead dev stays but it doesn't matter anymore because it's best practice and any med level dev has what they need to do their job, management understands the need for documentation and best practice and now your a big shop that cuts the bottom 2% of employees on a yearly basis.
spockspeare · 1 points · Posted at 01:00:57 on April 27, 2018 · (Permalink)
*precedent
justtogetridoflater · 1 points · Posted at 03:17:44 on April 27, 2018 · (Permalink)
The issue is, this is often suicide. If it is always possible to fire the person who wrote the code, then there's no bargaining power except that they do good work.
iamanoctopuss · 1 points · Posted at 13:14:48 on April 28, 2018 · (Permalink)
There's a word that non IT based businesses have stolen from software engineers, 'agile development'.
sometimescomments · 1 points · Posted at 20:52:20 on April 29, 2018 · (Permalink)
In my experience, documentation quickly falls out of date, aside some high-level stuff. I trust reading the code (and hopefully relevant and useful) comments over any diagram or something not connected to give warnings during the build process.
nickiter · 1 points · Posted at 21:37:56 on April 29, 2018 · (Permalink)
That's just a sign of bad practice, imo. If documentation doesn't get updated, you might as well not do it.
sometimescomments · 1 points · Posted at 21:49:34 on April 29, 2018 · (Permalink)
I agree. I feel I document well, but when I approach a new project I don't fully trust documentation if it isn't tied into a build process. Too easy to overlook and it's not the source of truth.
nickiter · 2 points · Posted at 22:32:41 on April 29, 2018 · (Permalink)
Legit. I don't trust people just as a rule lol.
Lacotte · 1 points · Posted at 22:18:36 on June 1, 2018 · (Permalink)
TIL a new awesome word, lol. Thanks!
Swie · 197 points · Posted at 15:16:11 on April 26, 2018 · (Permalink)
Right. The sane approach to this is to identify exact parts of the problem that you don't like, and fix those, one-by-one, keeping in mind the others but writing modular code so fixing one part doesn't break the entire system or require a cascade of giant changes. You should have well-defined interfaces between parts so you can keep the same interface (or make minimal well-understood changes to it). If you don't have an interface the first step is to create one.
I do this regularly on my current project, I've worked on it for 5 years now and can identify bad design choices from the past. The solution is to, when an opportunity presents itself (for example, new features or bug-fixes), take time to make changes to the architecture of that part of the code.
Also when making changes you should have justification for it (future-proofing or simplifying the code is a valuable justification). That way you know it's not a vanity project because you have to actually be able to explain to people what exactly was wrong, and why.
lukeautry · 131 points · Posted at 16:04:27 on April 26, 2018 · (Permalink)
Yeah, this is a great attitude and is well expressed in Refactoring (Martin Fowler).
I think part of what makes good programmers good is that they're not afraid to attack hard problems. A certain amount of irrational optimism or fearlessness is, at least for me, a helpful attribute. If you find yourself saying "how hard could it be" a lot, this is probably you.
You just have to be self-aware enough to know that your optimism is actually a productive form of delusion sometimes.
cville-z · 58 points · Posted at 19:42:49 on April 26, 2018 · (Permalink)
Larry Wall is famed for saying that three virtues of programmers are laziness, impatience, and hubris (relevant text is at the end of the article). Laziness means you only want to do things once ever; impatience means you don't want to wait for someone else to fix the problem; hubris means you think you can do it better than anyone else.
a_blue_ducks · 111 points · Posted at 18:20:35 on April 26, 2018 · (Permalink)
Absolutely. I get frustrated at programmers who throw their hands up at things too fast. Recently at my (quickly-growing) company, we've been trying to divide up responsibilities for different parts of the app, but some of the leaders of other teams will say "but you guys are the most knowledgable about X". And my response is always "nobody explained X to me, I went in there and figured out how it works and that is why I'm now expert on X. Your team can do it too - I'm willing to help, but you have to put in the effort". Rant over haha
fzammetti · 24 points · Posted at 02:47:23 on April 27, 2018 · (Permalink)
I agree with what you're saying, but it also subtly hints at a key problem: the number of times I've had to "just get in there" is kind of ridiculous. We don't put enough emphasis on good technical documentation generally these days.
Ever see the documentation for things like the Apollo flight computer system? It's masterful! Everything explained, in words and not just diagrams... lots and lots of details. Looking at the code itself is almost an afterthought because by the time you see it, you already understand it.
Nowadays, we throw around terms like "self-docunenting code" and we say things like "the code is the only source of truth" and those things are certainly based on sound thinking, but we seem to think it's ALL you need. It's really not.
Imagine a new programmer on the Apollo program being told "just get in there" and explore the code. Somehow, I doubt that ever happened.
We need to write good, self-documenting code - and then we need to go properly document it anyway. Nobody should ever have to understand a system just by trying to decipher the code because for the reasons Joel talks about, that's hard. It IS the final source of truth, that's true, but it shouldn't the ONLY source of truth.
XANi_ · 5 points · Posted at 08:51:40 on April 27, 2018 · (Permalink)
Well I bet Apollo didn't have non-technical manager pushing for impossible deadlines.
And if your argument can be backed by "someone will die if we fuck that part up, in a big, expensive explosion" I bet people tend to listen more carefully
a_blue_ducks · 3 points · Posted at 15:03:39 on April 27, 2018 · (Permalink)
For real! There is a massive difference between trying to make a lot of money and trying to send living beings to outer space. Writing legible code is the most straightforward way to help out those who come after you, including your older self.
fzammetti · 2 points · Posted at 17:34:22 on April 27, 2018 · (Permalink)
Fair point. But then again, maybe if we pretended we were all trying to keep rockets from exploding we'd do better work as an industry on the whole, 'cause right now we're really not. We fool ourselves because we've learned to make systems that somehow do the job, but we ignore all the warts under the covers that gets us there and we think the ends (it works) justify the means (it's not documented and is written poorly).
Code that isn't maintainable isn't good code at the end of the day, whether it's launching rockets or processing beanie baby purchases online (even if the potential bad outcome isn't comparable).
XANi_ · 3 points · Posted at 19:19:27 on April 27, 2018 · (Permalink)
Well it is definitely a good attitude to have. But it takes a lot to push it. You pretty much have to be in "position of power" (at least be one of senior programmers in the group, if not architect) to push for it, and you pretty much have to have at least some support from management (at least enough for them to not just fire you).
Current methodologies aren't exactly very useful for it either
fzammetti · 2 points · Posted at 20:56:28 on April 27, 2018 · (Permalink)
True, and it's really that later point about management support that matters. I say this as someone who has been in a position of power for many years. I've definitely managed to affect some degree like I'm talking about, but I've never had what I would consider "proper" management support... not fully at least... so there's only so far I can move down the field (and honestly, management sometimes gets more blame than they even deserve: they have to make hard choices about what's going to be best for the business, and sometimes there's no choice but to think tactically, and that's when it's so very easy to allow standards to be pushed aside in favor of expediency). It is, as you say, largely a consequence of modern methodologies almost institutionally not allowing for it anymore.
Ah well, it DOES keep us employed anyway :)
XANi_ · 1 points · Posted at 22:44:56 on April 27, 2018 · (Permalink)
To be fair, you do not always know if a given piece of code will be even used in 6 months or in a year so trying to get everything to same high standard can be a huge waste of time.
Of course, if a given component does survive that long there is a good chance any maintenance or refactoring on it will be net positive but likely response from manager is "well it worked for a year, why need to work on it now?"
I'm in... "interesting" place where I am hired as a sysadmin but do that around 40% of the time and rest is mostly programming (mostly automation and integration of various systems, other guys in departmen do more of sysadmin stuff) so in a way I'm my own manager when it comes to programming and honestly almost every single time I decided to spend some extra time even tho it already "kinda sorta worked okay", it was worth it.
But that's a perspective for systems that usually run at least years (and only get upgraded, not replaced) so I already know at the moment of writing that it will probably be used for a long time. That isn't the case in a lot of software projects.
pdp10 · 1 points · Posted at 22:26:08 on April 27, 2018 · (Permalink)
Apollo had three deaths, which slowed down parts of the program. Maybe those deaths led to higher standards later.
[deleted] · 1 points · Posted at 10:54:18 on April 28, 2018 · (Permalink)
You’ve heard of the Space Race, yes? Whatever else the Apollo program had going for it, they were under enormous time pressure.
People did die.
tcpukl · 1 points · Posted at 11:43:02 on April 27, 2018 · (Permalink)
Apollo missions are critical systems. The same as a nuclear power station. They also have formal proofs they work too the design spec. You can't apply the same to business software. They are just too big and often doesn't even have a design spec.
fzammetti · 2 points · Posted at 17:30:22 on April 27, 2018 · (Permalink)
You said two things there that are interesting to me... first, are you saying that the control system software for a nuclear power station isn't bigger than most business software? 'Cause I would disagree with that (though I'll concede it's true for the Apollo software). Not really a big point though I suppose. The second thing is thatbusiness software often doesn't have design specs, which is true (nowadays thanks to Agile anyway), but I would ask: don't you see that as a problem?
We've kind of gone down this rabbit hole over the last maybe 10 years (and I've done it in my company over roughly that period so I know full well how it is) where we do exactly as you say, and I often times wonder if people really understand the consequences of that path. Rapid iteration is great. Reduced time to market is great. Not writing a ton of documentation up front is great (maybe). But the consequence is that what you deliver is nearly always flawed and you accept that and iteratively fix it. I often wonder if that's really the right path for most businesses to take, at least for some subset of work.
I very much remember the days of writing BRDs and TRDs for months before a single line of code was written. It's certainly more fun nowadays, but the quality of what we deliver doesn't seem to match up, not initially and really not even after iterations because the sooner you start patching code is the sooner you start making it ugly code. And, when you sometimes have to do large refactorings because the architecture wasn't as well planned out as you'd like, that ugliness gets multiplied. You seem to always wind up with worse software, though at least you did it fast. There's this belief in "fail fast" as a viable strategy, and I'm definitely not convinced it's the right answer (again, for some subset of work - I don't think this necessarily applies to every project).
Maybe if it did have design specs, if we did have formal proofs for the things that logically can have formal proofs at all, and we backed away from Agile at least a little, we'd be in a better situation.
tcpukl · 1 points · Posted at 21:31:48 on April 27, 2018 · (Permalink)
I totally agree with everything you say, except may be it depends on which software we compare to critical systems.
I've never worked in 'business software', only 20 years in games software, after a Computer Science degree in the late 90s.
I think another big issue with being able to prove everything is the fact of inheriting old code. If you started from scratch, surely you could break down and prove everything. But if the code isn't written from the formal proof in the first place then your stuffed.
fzammetti · 1 points · Posted at 21:41:28 on April 27, 2018 · (Permalink)
All good points.
bsinky · 1 points · Posted at 12:55:34 on April 27, 2018 · (Permalink)
But I think it's the only guaruanteed source of truth. Documentation can become incorrect or outdated when code is updated and someone doesn't also update the documentation.
fzammetti · 3 points · Posted at 17:17:45 on April 27, 2018 · (Permalink)
Definitely true, but I've always thought that comes down to treating documentation (whether in code or not) as being of equal importance and expecting the same sort of diligence and professionalism in maintaining it as we expect in maintaining the code itself.
For example, if you see a comment on a method that doesn't reflect what the code is doing because it's changed over time, isn't that really just a matter of diligence? A matter of responsibility? Fix the comment at the same time you fix the code and there shouldn't ever be out of date comments. Treat them with equal importance and it shouldn't ever be a problem.
pdp10 · 1 points · Posted at 22:36:08 on April 27, 2018 · (Permalink)
It's all there in the
git blame.a_blue_ducks · 1 points · Posted at 15:06:30 on April 27, 2018 · (Permalink)
Yep, I started out my career writing lots of documentation, and I've actually regressed a bit on that because of how easily things get out of date. I'm all for good comments explaining why something is done a particular way, but not for comments that try to tell you what the code is doing. That's what the code is for!
In lieu of comments telling what the code is doing, I spend a little extra time refactoring until I have functions that tell you a story. If you want to know the details of a piece of the story, jump into a function. Most of the time you only will need the details to one spot.
MarsupialMole · 3 points · Posted at 23:41:29 on April 26, 2018 · (Permalink)
The basic domain requirements and public standards seem a bridge too far for many programmers. Wikipedia is an amazing thing too. Pretty sure I've made a career out of reading documentation and asking stupid questions. My programming skills are just a by-product of giving up trying to explain things I've read after being told a question with an obvious answer has to be referred back to "the business".
asdfman123 · 1 points · Posted at 20:52:13 on April 26, 2018 · (Permalink)
Even better programmers avoid hard problems (when appropriate) and use someone else's code to solve them.
eurasian · 13 points · Posted at 21:43:16 on April 26, 2018 · (Permalink)
The famous quote (well internet famous) "Programmers do things not because they are easy, but because we thought it'd be easy"
_crackling · 21 points · Posted at 19:11:16 on April 26, 2018 · (Permalink)
So i'm an aspiring developer.. and i dont think i classify as exactly a novice either, I've been exposed to this stuff for 20 years and always had a pretty good mind for programming. But I find my biggest road block is not being scared to tackle the hard problems, but the constant voice in my head telling me there's probably a better and more obvious way to handle this problem, and I get even to embarassed to ask for help out of fear my code looks ridiculous. Any suggestions on this?
xerods · 27 points · Posted at 19:21:20 on April 26, 2018 · (Permalink)
It seems you have two choices. If you implement something that is suboptimal people will know when they see it. If you ask someone if they have a better idea then they will be proud of themselves for contributing.
ThinkinTime · 3 points · Posted at 22:36:12 on April 26, 2018 · (Permalink)
I think this is why code/peer reviews are important. The job i'm currently at is very big on them and it has helped tremendously once I got over myself and stopped taking it personally. Every time someone goes over my code and points out the flaws or better ways to do it, it feels like I add another lego piece to my collection. Next time I do that, i'll have other, better options.
SurpriseAttachyon · 2 points · Posted at 21:58:35 on April 26, 2018 · (Permalink)
Yeah but then you wind up being the guy that the poster two post up complained about
sometimescomments · 13 points · Posted at 19:51:02 on April 26, 2018 · (Permalink)
It's hard, but try to be humble and not afraid to ask for a second opinion. Most coders love to solve problems and help peopl solve problens.
If you find yourself doing it too often, draft an email detailing the problem and what you think will fix it along with other options. The act of writing it out often solves it (i.e.: rubber duck programming). Or maybe even go for a walk. I've had great solutions when not focused on the problem (too much depth, not enough breadth).
iktnl · 8 points · Posted at 21:22:25 on April 26, 2018 · (Permalink)
If you review your code enough, you'll
You'll only hurt yourself and some poor sod in the future if you keep delivering "working" but unmaintainable hacks.
Feynt · 3 points · Posted at 20:09:23 on April 26, 2018 · (Permalink)
This is an easy one for me. The hard problems are usually hard because they're tightly coupled smaller systems. Don't look at an engine and say, "Man, that's way too complicated." Look at the spark plugs and pistons separately. Break down the fuel injector into more manageable parts. The same goes for programs. Sure it's a system that analyses billions of lines of text in seconds and outputs it in a completely different format as well as writes Excel spreadsheets and logs and stuff. But what's the pattern? It just takes things one to a dozen lines at a time, that's manageable. Figure out the parsing section separate of the export, Excel, and log sections. If you're just making your own stuff, think about the final goal and work backward, writing one little system at a time, and write the code to feed the output systems the data they need to do their jobs.
pdp10 · 1 points · Posted at 22:41:43 on April 27, 2018 · (Permalink)
Good analogy. When you know engines well, you can reason about them in the large and as a whole. When you're still learning them, thinking about isolated systems is vital.
Of course, engines follow certain design patterns, and these days don't differ tremendously within an application. An auto drivetrain engineer is still going to go back to basics if he's asked to work on a turboprop or a diesel-electric locomotive. Business systems can have more diversity.
Feynt · 2 points · Posted at 22:52:05 on April 27, 2018 · (Permalink)
Can and do are totally different things though, in my experience. Which is both exciting and depressing, and the reason I don't like enterprise programming. The exciting part is, "Hey! These crazy people actually do program like those guys in college!" So once you're there, you realise it isn't actually a field of high minded people casting a 1km shadow while you scrape through the bits trying to figure out what you're doing. The depressing part is, "Really? This buggy piece of crap that crashes on every day that ends in a Y is our production system? I just left a company that did this..."
pigvwu · 4 points · Posted at 20:34:21 on April 26, 2018 · (Permalink)
Exposure therapy. Show people your code often enough, and you'll get over it.
Also, try to accept that you will never write perfect code, but asking for help will make it better over time.
Silencer87 · 2 points · Posted at 19:37:44 on April 26, 2018 · (Permalink)
Create a design for your proposal, document the existing implementation and email that out to ask for feedback. This is what my group does when replacing existing code.
parkourhobo · 2 points · Posted at 20:55:27 on April 26, 2018 · (Permalink)
Your code probably does look ridiculous - and that's okay! Writing ridiculous code is the first step in learning to write elegant code. Don't be ashamed of mistakes - anyone who's done anything of note has made thousands.
Don't try to be perfect on the first try. Do it completely wrong, then go back and fix it. That's the best way to learn quickly IMO.
myrthe · 1 points · Posted at 22:58:45 on April 26, 2018 · (Permalink)
Write the first one as scaffolding. Write the first one as a rough draft. When asking say "this is my first approach but".
DON'T WRITE SLOPPY CODE. But write competent code that's good enough to solve the problem, and then look at refining it.
p1-o2 · 1 points · Posted at 08:51:45 on April 27, 2018 · (Permalink)
My advice is to get used to writing something wrong and then re-writing it. At work I might re-write the same part of a program 4 or 5 times before it's even ready to go into the master branch of code. You have to ultimately accept that you will get it wrong the first time and you'll fix it when you figure out why.
The hard part is recognizing when it's time to restart, and then motivating yourself to not throw your hands up while deleting your last 8 hours of work. Just gotta try your best. :)
pdp10 · 1 points · Posted at 22:37:58 on April 27, 2018 · (Permalink)
Being very familiar with the idioms of your language, being pretty familiar with the standard catalog of algorithms to solve problems, never doing something yourself when you should be relying on a standard library (like data and time handling), and code review.
SamSibbens · 2 points · Posted at 19:03:29 on April 26, 2018 · (Permalink)
That's what I said about many things.
Source: accomplished many things
More source: headaches from easier said than done stuff
dmanww · 2 points · Posted at 19:11:16 on April 26, 2018 · (Permalink)
The key is having some bloody minded stubborness to back it up so you don't give up
Phaenix · 2 points · Posted at 19:19:53 on April 26, 2018 · (Permalink)
Is this well worth the money? If so, I'm asking business approval to order one for myself/our team tomorrow. ^
lukeautry · 1 points · Posted at 19:28:08 on April 26, 2018 · (Permalink)
I think so. It's a good read with a lot of practical advice. There are a fair amount of code examples, but always paired with quality philosophical explanations.
softmed · 1 points · Posted at 19:35:07 on April 26, 2018 · (Permalink)
"The fool didn't know it was impossible, so he did it" - Unknown
There's a certain naivety that is required for accomplishing large things. If I 100% accurately knew how much work a project would take at the beginning, I would never start most of them.
singham · 1 points · Posted at 18:11:41 on April 26, 2018 · (Permalink)
Isn't this the very strategy adopted by Firefox in building Quantum?
recklessrider · 1 points · Posted at 20:10:20 on April 26, 2018 · (Permalink)
Or to be able to label it as you code
[deleted] · 1 points · Posted at 20:12:40 on April 26, 2018 · (Permalink)
Still, it doesn't matter how well defined your interfaces are or how separated the concerns or how elegant the snowflake. Software that is used, will be modified and the entropy of the code base will increase over time. Eventually the software will become brittle. The process can be slowed down, but it cannot be completely avoided.
billsil · 1 points · Posted at 22:54:55 on April 26, 2018 · (Permalink)
Don't future proof your code. You don't need it and if you do, you can do it later. One way to have more maintainable code is to just write less.
nachof · 1 points · Posted at 23:50:17 on April 26, 2018 · (Permalink)
In a previous project we had refactoring Mondays. If you found something that needs work but wasn't part of your current task, you wrote it down on the project tracker, with a refactoring tag. On Monday first thing, before doing any other work, you took a refactoring task and did it. We started with what was probably the shittiest codebase I've inherited. We ended up with something that while it wasn't perfect, it was pretty good.
mrcrassic · 37 points · Posted at 16:01:48 on April 26, 2018 · (Permalink)
But this now (potentially) creates two problems:
Their elegant might differ from what other developers on the team consider elegant, and
Now those developers need to learn Haskell to maintain this piece of code, a likely impossible task given the tech debt and fire fighting that comes with a 10M LoC codebase.
spockspeare · 3 points · Posted at 01:04:56 on April 27, 2018 · (Permalink)
Rule 1 of software teams: accept the way your teammates do things. Redesigning during code reviews is death to progress and a certain way to kill morale. If it works and doesn't violate the requirements (including global requirements for style or maintainability), ship that fucker. Let them know there's a better way, but don't make them change to fit your idealism.
mrcrassic · 6 points · Posted at 01:41:24 on April 27, 2018 · (Permalink)
Okay. Consider this:
You've just been hired as an Engineering Manager at a company. You inherited a team that is maintaining a 15-year-old codebase with very, very few "modern" software development practices in place (they have Git and use it, but they don't really have any practices for merging back into
master; they have Jenkins for CI, but it's really, really bare and is really only used to move code from their long-lived dev environment into QA and such). Releases are a huge pain, and introducing new concepts to said team is usually fraught with politics.What do you do?
spockspeare · 4 points · Posted at 03:45:45 on April 27, 2018 · (Permalink)
Tell politics to go fuck itself, keep the git, figure out how QA does its job but nothing gets merged back to the master branch, make sure the bug tracking system is operational, make sure verification is as driven as code, start jacking out releases (in whatever state they're in; that's what bug tracking is for) until it's second nature, and figure out where people like to drink on Fridays after work then go somewhere else myself.
mrcrassic · 2 points · Posted at 17:36:58 on April 27, 2018 · (Permalink)
Okay, but now you're changing team dynamic, which isn't accepting the way that the team does things.
The point I'm trying to make is that sometimes you do have to change the team dynamic to make progress, and that transition can be painful. Unless you have a perfect team where all of the engineers are self-motivated go-getters that work nicely together and are always comfortable with change.
spockspeare · 2 points · Posted at 19:49:32 on April 27, 2018 · (Permalink)
The way the team was doing things had problems, as mentioned in the problem statement. Nothing to do but lead them away from it.
You don't need to find the way everyone thinks is perfect (it probably doesn't exist if you didn't hire each of them into it). Just find a way they'll all accept that also solves the problems.
wuphonsreach · 5 points · Posted at 05:36:59 on April 27, 2018 · (Permalink)
Well, start with making a list of "what hurts?". Why are releases a pain? Are different teams using different workflows for git? How are issues / bugs / feature requests tracked? Where are the bottlenecks and bumps going from the developer's local copy of the code to production? What do teams do differently from each other? Where does it make sense to standardize?
And I agree that politics can go screw itself. If you have team members who actively or passively resist improvements and concepts, they need to shape up or be let go. Those EGR (extra grace required) people will kill your team's morale and ruin many attempts at improving things. They suck all the energy out of the room and the other team members just stop caring.
Where I work:
mrcrassic · 1 points · Posted at 17:38:20 on April 27, 2018 · (Permalink)
I agree with this list, but it does involve change...change that some people won't be comfortable with.
notabee · 2 points · Posted at 18:31:39 on April 27, 2018 · (Permalink)
How one approaches people can greatly dictate their level of resistance. It is a hard problem, though. The hypothetical engineering manager should have support from the rest of the business, and it would be really nice if some organizations piloted hiring social psychologists or counselors to assist with these kinds of problems instead of trying to achieve good teams using only the hire/fire approach.
mrcrassic · 1 points · Posted at 18:57:20 on April 27, 2018 · (Permalink)
That would be amazing. Firing people is really hard, almost to the point of psychologically trauma. (Imagine telling someone that's been a solid contributor and is providing for their family that they are no longer required. You just fucked up their life, even for a short bit. While we all should be prepared to deal with that, especially here in the US where most employers hire at-will, it is still traumatic to do that to someone you'd rather not do that to.)
notabee · 1 points · Posted at 20:59:39 on April 27, 2018 · (Permalink)
Yeah, no one wants to have to do that. But there would be some difficulties: strict confidentiality would be required in some cases. That might be hard for companies to swallow. It would need to be different from HR, where liability to the company is the primary concern and most people know well enough now to not overly confide. Coaxing out resentments and such would require some guarantee of safety.
pdp10 · 1 points · Posted at 22:51:22 on April 27, 2018 · (Permalink)
There's room for mentoring to be a solution here, if the decision-makers are interested in getting to the root causes of the problem, and the team has the bandwidth.
TEKC0R · 79 points · Posted at 19:56:58 on April 26, 2018 · (Permalink)
Amazing how relevant this is to me right now. I used to work for a dev tools company. They have a massive framework collecting code over the last 20 years. And a userbase of developers who rely on that framework.
About 5 years ago it was decided to deprecate the entire framework and start over. Most of the engineers were on board with this idea, but I never was. In public, I would basically stay silent, but in private they knew damn well that I thought this was a terrible idea.
It lead to turmoil between me and the rest of the team. Enough that 3 of them were able to fabricate some bullshit and get me fired.
The new framework was introduced. And it was missing a TON. No RegEx, no basics like hex or base64 encoding... it was a wreck. Customers never really got on board.
Yesterday the company announced they were giving up on that plan and doing exactly what I originally suggested: fix the damn problems.
For example, FolderItem.Item uses a 1-based parameter instead of 0-based like everything else. This is confusing and needs to be fixed. So don't throw away the entire class! Deprecate .Item and introduce .Child with a 0-based parameter. This is simple stuff, there was no reason to throw everything away.
I feel vindicated. But at the end of the day, that was my favorite job and I lost it. So this also just fuels the my rage.
hardolaf · 26 points · Posted at 06:10:40 on April 27, 2018 · (Permalink)
I work in avionics and our cardinal rule is:
If it flew, it's probably better than whatever you're going to replace it with.
TEKC0R · 5 points · Posted at 10:54:05 on April 27, 2018 · (Permalink)
I like that one.
GhostBond · 16 points · Posted at 23:33:34 on April 26, 2018 · (Permalink)
Yeah, that kind of thing pisses me off to no end. Especially when -
Yup.
The_real_bandito · 2 points · Posted at 03:45:38 on April 27, 2018 · (Permalink)
Wow this is some big kind of bullcrap. I will still be so mad if I was you.
TEKC0R · 5 points · Posted at 10:51:37 on April 27, 2018 · (Permalink)
I’m a very laid back and level-headed person. The people around me would tell you it’s very rare to see me genuinely mad. I try to let things go.
I’m not sure I’ll ever get over this though.
I’ve thought about revenge. I have ways I could hurt the company so bad. But that’s not who am I and my beef isn’t with the company so much as it is with those 3. I don’t want to hurt the company. I still want to see it succeed, even if I can’t be part of it.
captcrax · 3 points · Posted at 15:34:26 on April 28, 2018 · (Permalink)
Is it at all possible for you to get back in? Depending on the kind of bullshit that was fabricated, this might not be unreasonable. (e.g. "well, I know I was let go for allegedly stealing envelopes from the mailroom, but that was a long time ago and I've dealt with that problem. I still believe in the company, the product, and the people here, and I think I've got a lot to contribute.")
TEKC0R · 3 points · Posted at 16:04:49 on April 28, 2018 · (Permalink)
I honestly don’t know. On one hand, I’m still on good terms with the boss. I’ve been helping him pick parts to build his son a gaming PC. He was pretty much forced to let me go because those 3 said “either he goes, or we go.” In a small team, he couldn’t afford to lose all three.
On the other hand, I’m now making twice what I was before, so I’d be expensive. And I have no idea if the other guys could suck it up. Or if I could remain humble.
upievotie5 · 1 points · Posted at 06:00:53 on April 27, 2018 · (Permalink)
But those programmers got 5 years of job security while re-writing all that code, and that was probably what they were really thinking about.
TEKC0R · 2 points · Posted at 10:53:50 on April 27, 2018 · (Permalink)
I’m not sure it was that petty. This company has very low turnover.
whales171 · 1 points · Posted at 03:54:34 on July 21, 2018 · (Permalink)
You got to expand on this bullshit.
spockspeare · -6 points · Posted at 01:02:11 on April 27, 2018 · (Permalink)
Everything they've collected, I bet I can find ten things on github that do it better.
The_real_bandito · 3 points · Posted at 03:47:16 on April 27, 2018 · (Permalink)
Maybe but if you have a working product why do rewrite the whole thing? In the end it will end up introducing new bugs either way. Just take what you have and fix it.
What is it with throwing away old things instead of fixing what you have?
spockspeare · 1 points · Posted at 15:16:22 on April 27, 2018 · (Permalink)
New bugs are preferable to a code base that doesn't actually fit your requirements. There's a good chance that new processes and language improvements will reduce your bug rate. The caveat is that you have to retrain or replace your staff to have the skills to make it work.
The_real_bandito · 1 points · Posted at 04:30:26 on April 29, 2018 · (Permalink)
So you will re do a project everytime? Is that even cost effective? If you are going to retrain your staff why not 'retrain' them in following programming techniques that actually may help in keeping a project maintainable like functional programming?
spockspeare · 2 points · Posted at 15:47:05 on April 29, 2018 · (Permalink)
Depending on the context. You maintain existing applications for new releases on the same hardware, but occasionally redo it from the ground up because your old mistakes start to propagate inefficiencies throughout the rest of the code. Anything with significant hardware changes and full-boat verification involved, you're probably better off just starting from scratch, unless you designed it from the beginning to work on two platforms. If you did a really good job on generic utility code you'll probably keep that, but it's a small fraction of any big project.
carb0n13 · 18 points · Posted at 03:13:08 on April 27, 2018 · (Permalink)
[deleted] · 12 points · Posted at 19:12:40 on April 26, 2018 · (Permalink)
Isn't it more that over time the problem shifts slowly so that eventually the original breakdown is no longer relevant? For some period in between, hacks and workarounds are used to solve the new problems with the old framework, until eventually it becomes so time consuming that it makes sense to re-write the whole thing based up updated assumptions. Then the process ineveitbly starts again.
arendjr · 1 points · Posted at 11:17:44 on April 27, 2018 · (Permalink)
That’s certainly a part of it, but you sound like you’re assuming the framework is set in stone. Why not let it evolve gradually over time as well?
cyanydeez · 1 points · Posted at 12:58:28 on April 27, 2018 · (Permalink)
I think the reality is that the more problems we ask a framework to solve, the more, perhaps exponential, the edge cases exist.
yur_mom · 30 points · Posted at 19:30:12 on April 26, 2018 · (Permalink)
I could solve it in one line of perl.
jokullmusic · 26 points · Posted at 21:21:07 on April 26, 2018 · (Permalink)
I can solve it in one line of Python!
zuchuss · 5 points · Posted at 22:50:36 on April 26, 2018 · (Permalink)
Importing a library does nothing without calling a function you dolt
Everyone knows that:
Import solution
sol = solution.answer.get(problem)
Axmouth · 4 points · Posted at 12:27:33 on April 27, 2018 · (Permalink)
The module you import can contain code that executes itself, many do in fact.
zuchuss · 1 points · Posted at 15:07:58 on April 27, 2018 · (Permalink)
Not really. A class library is just that and its purpose is to provide types and methods/functions/subroutines/whatever you want to call it for the application to explicitly call. What you probably meant to refer to are IIFEs, and modules do have them for initialization of constructors and such, the scope is seldom above that for obvious reasons. Then of course there's monkeypatching as was mentioned.
Axmouth · 2 points · Posted at 16:20:10 on April 27, 2018 · (Permalink)
My point is simply that I can import in Python and have code executed.
Doesn't matter how you define a class library, it's something that can be done very easily. So "import solution" could very well be a valid program if so desired. Just like "import antigravity" from the system libraries executes an action.
It is indeed not how most libraries are implemented(or should imo), it is however an option and the previous commenter was not wrong.
zuchuss · 3 points · Posted at 20:03:29 on April 27, 2018 · (Permalink)
That's fair, can't argue against the best kind of correct.
lx45803 · 3 points · Posted at 05:19:07 on April 27, 2018 · (Permalink)
The library monkeypatches the function that is breaking.
zuchuss · 1 points · Posted at 15:15:43 on April 27, 2018 · (Permalink)
Tru dat
spockspeare · 2 points · Posted at 01:05:21 on April 27, 2018 · (Permalink)
Okay, here's what you need to solve:
Evaluate any given line of Perl.
flukus · 3 points · Posted at 22:36:23 on April 26, 2018 · (Permalink)
I'm working on a product now who's sole purpose is to import CSVs in various formats. It features a plugin system with dynamic loading, our own special regex language and all sorts of overengineering. To add a column to one plugin took me a week and I had to touch 12 files held in a delicate balance.
10s of thousands of lines of code and I'm pretty sure it could be replaced with a dozen short bash/perl/awk scripts.
[deleted] · 3 points · Posted at 03:07:36 on April 27, 2018 · (Permalink)
[deleted]
flukus · 2 points · Posted at 04:49:07 on April 27, 2018 · (Permalink)
It basically translates the csv files into SQL insert statements, there's very little validation to do and the supervisor process doesn't do much.
It's a simple problem that was made complex by Devs trying to solve a more interesting meta problem.
pdp10 · 3 points · Posted at 22:59:25 on April 27, 2018 · (Permalink)
Write some tests and then write a new implementation against the tests.
CSVs are kind of a worse-case record format, though, for historical reasons and because of data and i18n concerns revolving around the record separator ','. TSV is much simpler, more elegant, and less likely to go wrong. But ASCII itself has group, record, and unit separators since the mid 1960s, because record-based files used to form the backbone of data processing with computers.
I've worked with ETL systems and the records are never the unexpected or interesting part.
Nicksaurus · 2 points · Posted at 22:58:03 on April 26, 2018 · (Permalink)
Or one 12-kilobyte regex
michi-e · 1 points · Posted at 21:29:48 on April 26, 2018 · (Permalink)
https://www.reddit.com/r/ProgrammerHumor/comments/8452i9/perl_problems/
bananalamarama · -1 points · Posted at 20:14:29 on April 26, 2018 · (Permalink)
Your mom could solve it in one line of perl ...
e: 'tis because of his username
unkz · 2 points · Posted at 22:49:53 on April 26, 2018 · (Permalink)
Because that lady is really clever.
quangtit01 · 8 points · Posted at 20:38:30 on April 26, 2018 · (Permalink)
As a non-programmer, I understood all of this. You must be quite competent in your field that you are able to put it so elegantly in layman term, and I appreciate you for taking the time to do so.
justinmchase · 2 points · Posted at 21:16:40 on April 26, 2018 · (Permalink)
The problem is when its buggy and getting worse and is detrimental to the company and nobody knows how to fix it.
btreecat · 2 points · Posted at 21:24:12 on April 26, 2018 · (Permalink)
So more like throwing out the engine with the oil?
lukeautry · 1 points · Posted at 21:38:55 on April 26, 2018 · (Permalink)
Works for me!
satysin · 2 points · Posted at 01:06:08 on April 27, 2018 · (Permalink)
Yup. And that doesn't even cover that once a code base gets large and complex enough implementing it identically again becomes close to impossible and by then other big complex systems that interact with it that are designed to deal with how it works right now (bugs and all). So now you have at least one, usually more, additional code bases that needs to be changed and then another that uses that second system and keep repeating (often looping back round to the first system) and getting everything working properly becomes impossible.
[deleted] · 1 points · Posted at 20:05:43 on April 26, 2018 · (Permalink)
There are only two reasons to rewrite code:
legacy software that leads to old inefficient technology or incompatibility with new software (not legacy code)
performance optimization
If you can't read existing code, then you need to go back to school or get more training and experience from reading more open source code bases.
rdtsc · 1 points · Posted at 06:55:54 on April 27, 2018 · (Permalink)
I disagree. It's easy to write code that is hard to understand for someone else (or yourself later on). Bonus points if people try to be "smart" and play compiler, optimizing things manually because they think it's faster. But the only thing they are doing is obscuring the meaning.
issafram · 1 points · Posted at 19:07:56 on April 26, 2018 · (Permalink)
I once abstracted the data access layer in a project of mine. which used Entity Framework. so i made the POCO classes seperately for each implementation as well.
not the best ideas
role34 · 1 points · Posted at 19:52:27 on April 26, 2018 · (Permalink)
damn, i always thought this was wrong or felt wrong. I have this fear that if i don't know something in a problem or assignment, I'm not learning or progressing.
I guess it just means i can't know it all.
Supergaz · 1 points · Posted at 20:39:45 on April 26, 2018 · (Permalink)
Tell this to riot games
tehbored · 1 points · Posted at 20:40:41 on April 26, 2018 · (Permalink)
On the other hand, if you don't throw it out eventually, you'll end up having to hire programmers that know obscure legacy languages at double the normal salary.
deegwaren · 1 points · Posted at 20:49:32 on April 26, 2018 · (Permalink)
That'll only happen in twenty or so years, hardly the biggest problem.
ThatITguy2015 · 1 points · Posted at 22:59:24 on April 26, 2018 · (Permalink)
I would fully agree with this. With some of my projects, they will be thrown out because of how they were designed at the time. Low time, plus high push to finish on time led to something that does exactly what you want it to do, but does not look good and definitely has room for optimization.
spockspeare · 1 points · Posted at 00:56:18 on April 27, 2018 · (Permalink)
That isn't wrong. The truth is, 90% of "reuse" is misguided. Start with new requirements and write new code using new methodologies. The way the people who are getting rich are doing.
B00Mshakal0l0 · 1 points · Posted at 01:11:17 on April 27, 2018 · (Permalink)
Either that or the code is complete garbage, the UX interface is trash, and all the feedback is horrendous...
[deleted] · 1 points · Posted at 01:28:49 on April 27, 2018 · (Permalink)
So what you’re saying is that Bluehole can’t scrap PUBG because it’s making so much money despite its shitty performance, and recoding it is the proper way of handling it. Gotcha.
RunninADorito · 1 points · Posted at 02:26:37 on April 27, 2018 · (Permalink)
SOA or micro services are the answer. Well, at least part of the answer.
cdarwin · 1 points · Posted at 05:24:16 on April 27, 2018 · (Permalink)
I am currently the custodian and maintainer of approx 500K lines of C++. I began working on this particular project in 2007 with a senior team. They have all since retired or moved on. Fortunately, the code is highly modular and very well organized. But I am "the dude" now, and I feel like I only have a deep intimate understand of about 40% of this software. But because it is well organized, when bugs are found (and they are still found), I can usually trace the problem down in an hour or two.
kskulski · 1 points · Posted at 07:46:56 on April 27, 2018 · (Permalink)
Which is why simpler more readable code is often better than clever elegant code. If someone later has harder time figuring it out it isn't worth it. Maintainability is usually more important than performance.
cballowe · 1 points · Posted at 08:03:37 on April 27, 2018 · (Permalink)
There's another half of the problem as code ages. There's a case where every step of evolution in the code made sense given the previous state and the goal of the developer at that time, but collectively they are no longer the most direct way to represent the total system. There's also sometimes the results of incomplete refactoring and other ways for hard to understand code to creep in.
The big reason that I think rewrites lead to better code, though, has nothing to do with any of that. It's that if you're forced to rewrite code, you end up throwing away some features that no longer have value to the system. I have a theory that a huge chunk of the "it would be so much cleaner if we rewrite it in a different language" turns out to be true is just the fact that changing languages means you lose some ability to just copy the code you don't understand into the new place (or call the existing libraries, etc). If you want the functionality, you need to understand it and implement it. That also means your reviewers are likely reviewing it in one change and not a series of 2-3 line edits spread over 30 people and 5 years.
HackSpirit · 1 points · Posted at 08:42:21 on April 27, 2018 · (Permalink)
This is like Vandalism.
cyanydeez · 1 points · Posted at 12:54:21 on April 27, 2018 · (Permalink)
I've realized that my initial concept never manages corner cases.
el_padlina · 1 points · Posted at 12:59:29 on April 27, 2018 · (Permalink)
Heh, at the project I'm at now it's not even the whole solution that can't fit person's memory. Just a single functionality in the code is so convoluted it hurts and to this day I haven't seen use cases for it documented anywhere, so only few people REALLY now what it's supposed to do but they keep that knowledge to themselves..
The spaghetti pattern resulting of years of maintenance and looking at the initial commits even initial creation was in some places shit.
There are ways to avoid 25 parameters in a single method ffs. Or classes that span over 1k lines and do a lot of things not related to their domain. Or methods with 200-300 lines and complexity of 20+.
snerp · 1 points · Posted at 16:27:22 on April 27, 2018 · (Permalink)
I've seen some amazingly bad systems, but even then I was able to salvage 'something' out of the old system. Stored Procedures, some business logic, maybe some html or images. Even if it's a dumpster fire, you can still use the dumpster.
DrunkMc · 512 points · Posted at 14:30:54 on April 26, 2018 · (Permalink)
I think most code, no matter how well designed before hand, is designed mostly on the fly. You always run into things you didn't think of and adapt. This leads to cludges and breaking the design. Once everything is done and it works, I love nothing better than tearing it all down and re-writing it with all lessons learned.
ralphpotato · 121 points · Posted at 19:48:50 on April 26, 2018 · (Permalink)
I find this to be the case when I teach students. For homework problems which may be encapsulated within only 100-200 lines, I actively advocate for saving a copy of their non-working code once they figure out what they need to do, and re-writing from scratch using their old code as reference and their knowledge gained.
I think computer science/programming students have too much of a habit of hanging on to their old code because of the sunk-cost, but in reality it's easy to overlook some small bug in your code if you're only reading and not re-writing.
I would say that for even large code bases, as long as the constitutient parts are abstracted out, re-writing a large section isn't bad. That's the whole point of abstraction anyway. It's just getting to that point where you can easily rewrite disjoint sections of code is hard.
rush22 · 21 points · Posted at 22:43:26 on April 26, 2018 · (Permalink)
Yes it's a great way to learn, but bad for business.
Tasgall · 28 points · Posted at 03:16:03 on April 27, 2018 · (Permalink)
It depends, sunk cost fallacy is bad in business as well.
eddyparkinson · 4 points · Posted at 03:20:33 on April 27, 2018 · (Permalink)
That is a good method. The next step is pseudo code/PDL - read "code complete" by Steve McConnell - the section on PDL.
That said - the thing that changed how I code the most is doing the exercises at the back of "A Discipline for Software Engineering" by Watts S. Humphrey
I would say these 2 have changed how I code more than any other book.
NAN001 · 27 points · Posted at 20:38:39 on April 26, 2018 · (Permalink)
I do exactly the contrary. When given a big spec, I usually feel overwhelmed on how to architecture the solution because there are so many things to think about, so I simplify the problem, temporarily ignoring some requirements or even features. When I say "ignoring", I mean literally. I start designing, then programming, a first iteration of the thing, totally incomplete, pretending it's the end product. Once I know this iteration is done and solid, I add more stuff from the spec. I study how the existing code must be refactored and changed to host the new requirements (which weren't actually new), which often involves a bit of code rework, and this way I build the next iteration. And so on.
Depending on the context (deadlines, co-workers, priorities, etc), I can apply this process more or less properly, and I know that when I apply it properly I produce the best of code. The main difference I find between this technique and the "agile" process where new requirements appear out of nowhere (which I could theoretically integrate gracefully into the existing iteration following my technique), is that a finished spec has some sort of consistency whereas many actual new requirements makes no sense and come with a weird sort of inherent complexity as if it was fundamentally incompatible with the original requirements.
uptokesforall · 7 points · Posted at 22:15:55 on April 26, 2018 · (Permalink)
I like this train of thought because you build up the conceptual model with variations of a working model
irqlnotdispatchlevel · 2 points · Posted at 19:41:27 on April 27, 2018 · (Permalink)
Pretty much this.
pdp10 · 1 points · Posted at 23:02:54 on April 27, 2018 · (Permalink)
In most agile methodologies, it's not required for the team to accept the item. Either don't accept it into the backlog, or give it the scarlet letter of "Epic" until you can devise a strategy for it.
hugokhf · 45 points · Posted at 19:38:39 on April 26, 2018 · (Permalink)
Once everything is done and works, I just like to leave it alone. Are u the werid one or am I the weird one?
Oncra · 24 points · Posted at 19:59:49 on April 26, 2018 · (Permalink)
I think the best practice is to constantly review and refactor existing code (assuming you have the manpower to do so). That can be hard with management that doesn't understand the process or with programmers who want to always work on the latest and greatest.
The long-term benefits and business value of moving from "good code" to "great code" with a little bit of love is immeasurable.
fuckingoverit · 7 points · Posted at 03:39:04 on April 27, 2018 · (Permalink)
Really depends on your test coverage. I know a lot of places where you’d have a hard time explaining to management why you “fixed something that isn’t broken” and then broke it. Maybe financial software is just a different beast altogether and other realms are less intense
wuphonsreach · 1 points · Posted at 05:45:57 on April 27, 2018 · (Permalink)
I'm a strong proponent that refactoring requires good automated test coverage. And as much as possible, that should be tests that can be run locally by the developer, in under 10 minutes (preferably 5 minutes). If the IDE can run them automatically as code changes? Even better.
In the real world, that's not always possible with legacy code. So you may need to start by doing a minimal refactor of the code to make it more testable (dependency injection, etc.). Or make other changes to the system to enable faster tests.
m50d · 1 points · Posted at 09:38:49 on April 27, 2018 · (Permalink)
Finance has its own weird conventions because everything is so tied to trading hours, so your code actually doesn't need to be that resilient over the long term (you can have 2 hours' downtime every weekend and no-one cares - the people who work on e.g. AWS would kill for that) but it's absolutely vital that nothing goes wrong during market hours on a weekday.
uptokesforall · 3 points · Posted at 22:05:58 on April 26, 2018 · (Permalink)
I agree but sometimes that move may be recreating the design in another language. Some languages are better than others at some things
The_real_bandito · 2 points · Posted at 03:49:27 on April 27, 2018 · (Permalink)
What programmer doesn't want to work on the latest lmao.
bmarkovic · 2 points · Posted at 09:55:54 on April 27, 2018 · (Permalink)
This!!!!
Tasgall · 2 points · Posted at 03:18:20 on April 27, 2018 · (Permalink)
You're not weird, you're just not considering the future additions to the project that will be massive undertakings in the old kludgy system but could be easily done in a system developed in hindsight.
Thomasedv · 2 points · Posted at 20:04:53 on April 26, 2018 · (Permalink)
I'm just coding in python for fun, but I'm never done with my projects. There's always something to change. And there's always a ton to do. From fixing all the bad solutions from when I did know better ways, to structuring, renaming, and documentating. Not to mention a new feature, or better coving for edge cases or other unlikely but possible situations.
I am learning as I go along, and some things are just so massive it'll take ages to learn, but you can get solutions that work, but later find much better ways to do things.
bagtowneast · 38 points · Posted at 19:05:05 on April 26, 2018 · (Permalink)
And this is where people go wrong. If you discover, once you start implementation, that your model doesn't fit, stop! Think about how you need to change your model to accommodate this new data. Refactor/rework now, before you commit to a path that you now know doesn't work. Doubling down on a bad path is, long term, considerably worse than investing in the right plan early. At least in my experience.
JarredMack · 73 points · Posted at 20:53:23 on April 26, 2018 · (Permalink)
Cool man, I need you to do that by Friday tho since we have a deadline, that cool?
SteveBIRK · 18 points · Posted at 21:11:47 on April 26, 2018 · (Permalink)
Also product changes the requirements and QA found a bug with another one of your PRs.
bagtowneast · 12 points · Posted at 21:22:06 on April 26, 2018 · (Permalink)
Oh, I love that. I've experienced it directly. Bug tickets filed because requirements changed but were not communicated. That's not a bug, that's a project manager failure.
Chordreich_ · 2 points · Posted at 10:35:02 on May 1, 2018 · (Permalink)
PRs? What's a PR? I don't think subversion has a "PR"... Anyway, someone else on the team just pushed code into QA, and no-one will fess up to it. We're having a meeting to discuss this in 10 minutes, because it's Friday tomorrow and we have to demo our failures to steakholders.
bagtowneast · 4 points · Posted at 21:20:55 on April 26, 2018 · (Permalink)
Well, then, we're going to have to discuss how this changes the deliverables for Friday. The scope of the project is different than was anticipated.
Also, if you're iterating and measuring, by the time actual delivery comes around, this should be worked out already.
And my final point is that eventually, we have to be willing to say we're not going to ship unless a certain quality bar is reached. Sure there are compromises, but in my opinion, many developers are way too willing to sacrifice code quality to meet unrealistic management demands. That's a fool's trade.
cortesoft · 11 points · Posted at 23:50:22 on April 26, 2018 · (Permalink)
I think the context of the work really matters.
I work for one of the largest CDNs in the world. We HAVE to keep it running, and it has to have 100% uptime. This is the facts of our business.
What happens as we grow is that we are constantly hitting new bottlenecks. Things that worked fine with 30 thousand servers suddenly stops working at 35 thousand. Nothing scales perfectly horizontally.
So, we now are up against the clock. We know our system is teetering towards falling over, and we can keep it up for the near term with a lot of massaging and duct tape, but we need to write some new code to fix the bottleneck.
We can’t just say, “we aren’t going to ship yet unless we meet a certain quality.” Not shipping is not an option, because not shipping means hundreds of millions of dollars lost and 1000 people out of a job.
Obviously, we try to avoid these situations whenever we can, and most of the time we are planning out work in advance and spending the proper time to build with quality, but the unexpected still happens.
Don’t tell me I am a fool for sacrificing quality when the alternative is the collapse of our entire company.
JarredMack · 8 points · Posted at 00:16:17 on April 27, 2018 · (Permalink)
Yeah, I can totally understand and agree with OP's ideals, but that's just not how the real world works. Experience will teach developers how to make the decision on whether those extra 4 weeks of developer time to make sure a solution is "correct" are justifiable for the business in both the short and long term
bagtowneast · 1 points · Posted at 00:34:23 on April 27, 2018 · (Permalink)
I'm sorry that you felt personally insulted by my statement.
I agree that my positions are rather idealistic. It's just been my experience that sacrificing quality has a much longer-term cost than people realize, no matter what scale you operate at. And I strongly believe that being putting in the situation of having to make that choice is a sign of failure elsewhere. It seems clear to me that if one ends up at the point of having to make that last minute choice, well, the horse has already left the barn. You're already in a reactive-only mode.
And, please don't take this the wrong way, but if the choice is shipping this change or the entire company collapses? Well, that seems rather hyperbolic. And if it's not hyperbole, then I would be seriously concerned about the viability of the company.
cortesoft · 2 points · Posted at 03:42:30 on April 27, 2018 · (Permalink)
I am sorry for the tone of my reply, I wasn't trying to come off as personally insulted. My last line was certainly over dramatic.
I also realize I might have made it seem like our company was constantly behind the eight ball, always completing things at the last minute just well enough to get by. That isn't the case at all; most of the time, we have plenty of time to plan and execute with quality and attention to detail.
The point I was trying to make was that that isn't always possible. If you work for a successful company, you get to a point where taking down time is simply not an option. And sometimes, unexpected things happen that cause issues that must be fixed with new code very quickly, and you sometimes have to take shortcuts to complete the work before things become so bad that you can't keep production up.
Now, of course, once you have the new code out, you absolutely should take the time to try to go back and improve that code, and make it more robust and easier to maintain. You can't, however, just choose not to push it to production until it is up to your highest standards.
As for it being hyperbole, it is in the sense that it isn't a super common occurrence; it isn't like we are facing this existential crisis every week. However, it is not hyperbole to say there has been times where not solving the problem quickly enough would absolutely put the survival of the company in danger. In many ways, a CDN is a commodity business; if we don't deliver absolute reliability, our customers would switch to a competitor in a heartbeat.
[deleted] · 3 points · Posted at 02:02:09 on April 27, 2018 · (Permalink)
[deleted]
bagtowneast · 1 points · Posted at 02:26:53 on April 27, 2018 · (Permalink)
I realize there are real consequences. I don't mean to suggest there aren't. But at the same time, management, product and various other stakeholders have to, at some point, be held accountable for unrealistic demands, promises made to customers without engineering buy-in and all the other ways they put engineering into these extreme positions of ship or sink, quality be damned.
Edit to add: next sprint? You should see the list of features we have lined up for that! We'll have to address that debt later....
appropriateinside · 18 points · Posted at 21:19:24 on April 26, 2018 · (Permalink)
This is very wrong.
Your first priority is to make something work, if you are tying yourself up on architecture before you even have a working prototype you're wasting everyone's time. You will run into yet another part of it that doens't fit the architecture you thought so hard about, and you're back to fussing over it again.
When you have something working, you know about all the moving parts, you know what goes where. Now that you know this, you can refactor it to be elegant and performant with relative ease.
Also a good quote:
bagtowneast · 4 points · Posted at 22:11:44 on April 26, 2018 · (Permalink)
Well, I didn't say anything about whether the thing was working or not. In my experience, you can't know whether your model fits or not until you've got at least a mostly working prototype. Nothing about recognizing that your model is incorrect prevents that. I agree, it sure looks like that's what I'm saying, so I apologize for not being more clear.
The problem, as I see it, is that everyone has a different idea of "Make it Work". For me, that's the minimal amount of code needed to exercise the most simple happy path of operation. (almost) No design survives that process. Where people go wrong is that they take that design and commit to it even though it's clearly not working. And then the kludges pile up and you're hosed.
But I should clarify that nearly all of my professional experience has been coming into startups that are trying to transition into not being a drunk teenager (the best way I know to describe startups). So that colors my views heavily. It's nothing but doubling down on bad design decisions, repeatedly, for years.
appropriateinside · 3 points · Posted at 22:24:10 on April 26, 2018 · (Permalink)
This accurately describes 1/2 of developers I know.They will follow very bad practices, and when you point it out, and the results of it. Instead of learning and looking into why they might want to change, they double down.
It's infuriating.
bagtowneast · 1 points · Posted at 23:09:45 on April 26, 2018 · (Permalink)
I've managed to come to peace with it. I work on making my corner of the world better. My manager calls it "a target rich environment"...
lcalculus · 1 points · Posted at 16:18:31 on April 27, 2018 · (Permalink)
It is not black and white, not all technological debts are the same. I agree is more important to make it work, but you need at least to make sure an affordable refactory will be possible to reach the next points.
sometimescomments · 1 points · Posted at 21:21:57 on April 29, 2018 · (Permalink)
Keep in mind that, I at least, can easily get lost in this. No, your data structure will never have more than 10'ish elements (i.e: provinces in Canada). I shouldn't spend any cycles on making it faster.
canmoose · 3 points · Posted at 21:08:03 on April 26, 2018 · (Permalink)
I feel like coding can be a lot like writing in general. When academics write papers or journalists write stories a significant amount of time goes into editing the writing. Papers and stories can be edited double digit numbers of times. I don't do this when im coding most of the time. Usually I code so that it functions properly, I don't go back and edit it like I would a paper. I try to make my code understandable when im writing but once I have a function name I usually don't change it for instance. So the code will get the point across, but its a first draft essentially.
[deleted] · 5 points · Posted at 20:47:24 on April 26, 2018 · (Permalink)
[removed]
coder111 · 2 points · Posted at 04:39:45 on April 27, 2018 · (Permalink)
Usually even if you do get to do a rewrite, you run into Version 2 problem.
Every idea and the kitchen sink gets thrown into Version 2, and it ends up over-engineered overcomplicated mess that is slower, larger and even harder to work with than Version 1.
GetOffMyLawn_ · 3 points · Posted at 19:43:29 on April 26, 2018 · (Permalink)
I worked in the defense sector. You literally spent years on design and documentation and review before you did anything more than a test stub or proof of concept.
TheDevilsAdvokaat · 2 points · Posted at 21:47:42 on April 26, 2018 · (Permalink)
Me too. I usually go through about three generations.
Minnesota_Winter · 2 points · Posted at 22:03:21 on April 26, 2018 · (Permalink)
And try NOT adding a buggy feature along the way.
Yeroc · 2 points · Posted at 03:03:55 on April 27, 2018 · (Permalink)
Yup, the first working program should be considered a draft the same way an author considers their first written version of a book a draft. Unfortunately, many developers stop at the first draft and consider it done leaving a mess. We're reading Clean Code by Bob Martin and this is an insightful comment he makes in his book.
DrunkMc · 1 points · Posted at 09:37:11 on April 27, 2018 · (Permalink)
I like that analogy a lot.
cyanydeez · 2 points · Posted at 12:59:30 on April 27, 2018 · (Permalink)
80% of the code solves 100% of the edge cases
sometimescomments · 2 points · Posted at 21:14:33 on April 29, 2018 · (Permalink)
Yeah. Nothing better than having a deep understanding of the problem and starting fresh on it.
thepobv · 1 points · Posted at 20:47:11 on April 26, 2018 · (Permalink)
This is doing it right though isn't? In most cases, if you've learned nothing from the system you built on how you can build it better if you had a second go round... then you learn nothing?
doesn't seems ideal.
JoeriVDE · -5 points · Posted at 16:12:04 on April 26, 2018 · (Permalink)
This
samjmckenzie · 11 points · Posted at 18:50:10 on April 26, 2018 · (Permalink)
If only Reddit had a feature that allowed you to show your support for a comment... Something like a thumbs up, or an upvote button...
JoeriVDE · 0 points · Posted at 20:27:50 on May 3, 2018 · (Permalink)
Ok, I won't reply next time.. Jesus..
BlackBettyWhite · -1 points · Posted at 20:32:42 on April 26, 2018 · (Permalink)
You might as well be home cleaning your apartment. You're not delivering any value to your employer by doing this.
irqlnotdispatchlevel · 0 points · Posted at 19:40:06 on April 27, 2018 · (Permalink)
You don't tear it down. You refactor it.
Here I have this module that had the first line of code written 6 years ago when I wasn't even part of the team. Since then, it went to 3 major redesigns, but we never tear it down. Because it was doing what it was supposed to be doing, and it was doing it the right way. It has a lot of bug fixes, edge cases discovered by mistake, cases that may happen once/year for a customer. I'm now one if its main maintainers. I recently refactored it again in order to simplify some things (mostly code cleanup).
If it would just disappear overnight and I'd gather together the developers who researched, created and fixed it along the time we will not be able to make it better. It might look better to us after we're done, we will probably avoid some design decisions that had to be fixed after its creation, but we will surely bring back old bugs and introduce new ones.
I have more trust in old code paths than in new ones.
chrisdoner · 1668 points · Posted at 14:11:26 on April 26, 2018 · (Permalink)
It's not a mantra without reason. I already have the quotes written up from The Mythical Man Month:
The whole point is that the first time you make any system, you don't know what you're doing. Every decision has a non-zero element of speculation. Some of those decisions will be fundamental. Insights from making the first system mean you can make the better decision without speculation the second time. If you try to keep the old system forever and just patch it repeatedly, that becomes an uphill climb: the longer you maintain a difficult-to-maintain system, the harder it becomes to maintain. You'll eventually reach your goal but you won't have planned for all the extra work. Even as the authors of a system.
Yeah, that's the problem with crappy code. You think that there's nothing wrong with it because it's been tested. But how do you know? Nobody apparently understands the code. Often, code is so bad that nobody knows how buggy it is. Look at OpenSSL, for a public example.
The code that programmers hate to maintain is when it's like walking into a haunted house and ghosts follow you around whispering seeds of doubt every time you open a cupboard or walk past a mirror. They'd prefer to set fire to it and put the fire out with holy water.
People like clean, simple code because it's obvious that it doesn't have problems.
JohnBooty · 367 points · Posted at 15:41:28 on April 26, 2018 · (Permalink)
I absolutely, sincerely agree with everything you said about writing software.
However, I think there's one thing that may be commonly misunderstood about Joel's original article:
I've always believed that Joel's article was written in the context of a software company choosing to rewrite its core product from scratch, and this article was written in back in 2000 when "being a software company" pretty much meant "you ship regular versions of your code, and sell them to customers, and if you miss/botch a release maybe your company will die, especially if that product is your only product."
Within that context, yeah, rewriting code from scratch is a very, very dangerous thing to do.
I don't think Joel is advising that no code ever be rewritten, or even that no large project should ever be rewritten.
Or maybe I'm wrong! Maybe I'm giving him too much credit.
I still like many things about this article, even if the central premise is kind of a blanket statement that isn't always true, and is also kind of a strawman argument because most people don't mean "literally throw away all the old code and never look at it again" when they say "rewrite."
I like this part:
In my experience, this is true. The "old code" generally has a lot of these little hacks and kludges to fix real-world problems. No matter how beautifully an application is (re-)architected, there are always going to be bizarre little things that just have to be dealt with, even if they junk the code up a bit.
justfiddling · 74 points · Posted at 18:25:58 on April 26, 2018 · (Permalink)
Corner cases gonna corner. No matter what.
noknockers · 9 points · Posted at 20:22:32 on April 26, 2018 · (Permalink)
And edge cases gonna edge
Psyladine · 9 points · Posted at 20:23:59 on April 26, 2018 · (Permalink)
"look at this thing, all these corners! Customer didn't order a d20! Let's scrap this and start all over with a nice round, simple ball."
m50d · 2 points · Posted at 09:44:18 on April 27, 2018 · (Permalink)
Not always. Sometimes when you look at the problem the right way, all the corner cases become ordinary cases. And generally that's what shows you've really understood the problem, because the business users normally don't think of their requirements as corner cases - they think "obviously you do one of those that way".
Occasionally you do meet genuine corner cases, but my rule is that the only legitimate reason for it to be a corner case in the code if it's also a corner case in the domain - the code should be as complex as the problem it solves, but no more complex.
phySi0 · 0 points · Posted at 13:13:24 on May 10, 2018 · (Permalink)
This is not the case. Code can be rewritten so that former corner cases no longer are. I can't be bothered to think of / find a screencast for a complex example right now, but a simple example of a pattern that destroys a corner case is the null object.
Not all corner cases are inherent to the domain, and approaching the problem with a new perspective may well remove certain corner cases.
guepier · 47 points · Posted at 19:09:53 on April 26, 2018 · (Permalink)
IIRC Joel has subsequently stated explicitly that he disagrees with Mythical Man Month about this. Or, rather, he said, in his modest way of speaking, “MMM is wrong here.”
Let's not give Joel altogether too much credit. He's smart, and he's influential for a reason, but many of the things he's blogged about lack nuance, are dogmatic, or go against what the evidence shows. And his business decisions are also quite hit and miss. The original FogBugz was written in his own VBA derivative, after all. And was subsequently rewritten from scratch in a sane language, ignoring his own written advice. So there’s that.
In his defence, even those articles where he was (in my view) wrong usually contain an interesting perspective and some good arguments.
bhat · 38 points · Posted at 22:13:06 on April 26, 2018 · (Permalink)
Sometimes the well-articulated arguments of a highly-opinionated person are valuable because they start a useful conversation, not necessarily because they're correct.
Xaxxon · 3 points · Posted at 23:20:02 on April 26, 2018 · (Permalink)
Rules are rules for people until you realize why they are rules. At that point you can understand them it’s appropriate to break them.
Nickolai1989 · 35 points · Posted at 18:55:41 on April 26, 2018 · (Permalink)
My own takeaway from the article, and I first read it when I was struggling to convince my team to avoid a rewrite, is that rewrites are often a fallacy. They're very tempting, for a couple reasons. For one, it's easy to make quick progress on a clean sheet project, and harder on a more mature project, so it's tempting if you're looking to make quick progress, but, naturally, the rewrite will slow down again as it gets more mature.
For another, and this is pretty much the title: more novice programmers haven't yet honed the skills to differentiate bad code from code that's hard to read. And that's not an easy skill. So they make a common mistake, which is to think that problems with the codebase stem from the code being bad, so they'll rewrite it with GoodCode(TM) and it'll be much better. Frankly, it's a pretty arrogant attitude.
Sometimes bad code really is bad code, and then you should rewrite that code. Sometimes bad code is just hard to read, and you should add comments or refactor it to make it clearer. But ultimately, try to have confidence that you're using the right tool for the job. Refactoring bad code is pointless if it's somehow flawed, rewriting hard to read code will just introduce new bugs.
I ultimately failed to convince my team to refactor instead of rewrite, and they spent about 2 years rewriting code that I estimated would have taken a few weeks to refactor. The leader of that team got fired.
rakenodiax · 28 points · Posted at 21:08:18 on April 26, 2018 · (Permalink)
The siren call of whole rewrites is so alluring because we see how elegant the first 90% of the solution is, but not the second 90% that introduces all of the ugly. Then it's time to rinse and repeat.
burnblue · 2 points · Posted at 04:00:50 on April 27, 2018 · (Permalink)
You can't have two 90%s! It doesn't add up!
I kid
zeuljii · 80 points · Posted at 18:23:50 on April 26, 2018 · (Permalink)
Those hacks and kludges need to be documented, associated with their cause, and forwarded to the manufacturer of the issue. When the issue is addressed they need to be revisited, or if not followed up on.
If you aren't tracking that... if your house was held together by string and tape, and you didn't know why, what would you do?
If I know the problem, I look for a better solution. If I don't, I rebuild.
JuvenileEloquent · 46 points · Posted at 19:15:26 on April 26, 2018 · (Permalink)
Good luck if it's a quirk of some major software company's product that is like that to be backward compatible or can't be changed for whatever reason. Sometimes you simply can't fix what's broken and have to tape over it.
I lost count of the number of code comments I wrote that detailed exactly why the obvious, clean solution can't be used.
zeuljii · 3 points · Posted at 21:29:17 on April 26, 2018 · (Permalink)
Yep, some manufacturers will never fix things. Some aren't even around, but for those who are, it's better they know. When you're a manufacturer it helps with priorities and awareness. As a consumer you can encourage them to break backwards compatibility.
In any case, you track it. You know who is fixing their issues, and you can respond when they do (or consider ditching them if they don't).
And sometimes you can't, for business reasons, get rid of a bad manufacturer. But at least you saved the next guy some time.
amunak · 8 points · Posted at 20:04:40 on April 26, 2018 · (Permalink)
You're right, but the point is to document those little things even when it might seem meaningless or obvious. Because when you later decide to update, rewrite or whatever, and this time maybe without supporting that old platform that you wrote the quirk for, you can simply remove the fix and cleanup the code even if the bug hasn't been fixed at the source. You simply no longer support it.
But when it isn't commented, eventually you end up with a huge, smelly heap of "tweaks" and "corner case fixes" but noone knows what each of them does, why, how they react to the rest of the code... And you end up having to rewrite it all from scratch instead of just having to remove most of the bad code.
JuvenileEloquent · 4 points · Posted at 10:54:01 on April 27, 2018 · (Permalink)
Personally I find this is the only legitimate case where comments are needed in your code. The "what" should be obvious, the "why" should be explained. Like "why" you need to check the JSON you're supposed to get back from this service isn't actually just a plaintext string that will choke the parser.
Comments are the meta-code to help you or the person after you understand the code at a higher level than simply "what does it do?", if you're not adding them then you're making it more difficult to maintain.
JohnBooty · 93 points · Posted at 18:59:49 on April 26, 2018 · (Permalink)
How long have you been working in the industry?
I've been doing this for 20 years and people look at me like my hair's on fire when I insist that those sorts of kludges be documented.
edit:
The reality is:
Unless you have been working in this industry under a very peculiar set of circumstances, you will spend time working with other peoples' code and it will have inexplicable things in the code.
edit 2:
In case it's not clear, I absolutely agree with you. A lot of the uncertainty associated with a rewrite could be avoided if people simply documented all those little hacks and kludges, so that future coders could make reasoned decisions about what's necessary logic and what's merely dead code.
Barbiewankenobi · 12 points · Posted at 21:14:47 on April 26, 2018 · (Permalink)
Yep. I literally removed an empty while loop and broke one of our programs. Shit gets weird sometimes. That loop should definitely have had (and now it does have) a comment saying "DO NOT REMOVE; HAS ODD PROGRAM-SAVING SIDE EFFECT."
kenpus · 5 points · Posted at 14:34:11 on April 27, 2018 · (Permalink)
The comment should really go into a little bit more detail, but it's positively much better than no comment at all.
antiname · 3 points · Posted at 01:28:23 on April 27, 2018 · (Permalink)
Did you put in that comment after you figured it out?
s-mores · 41 points · Posted at 19:36:06 on April 26, 2018 · (Permalink)
"Could we get rid of that thing that fixes the problem in a windows 98 browser? I don't think anyone's using that in 2018!"
"NO! You might break something!"
I wish I was joking...
salbris · 15 points · Posted at 21:15:20 on April 26, 2018 · (Permalink)
Get them data then don't work with assumptions .
Jess_than_three · 8 points · Posted at 22:50:20 on April 26, 2018 · (Permalink)
Not "no, you're wrong" - "no, that might conceivably cause some other unexpected problem". Totally different issue.
blackholesinthesky · 15 points · Posted at 22:51:55 on April 26, 2018 · (Permalink)
Me: "Hey team, since all major browsers have a considerable amount of support for ES6 I'd appreciate it if you could switch from using
indexOf()to check for inclusion toincludes()"Dev: "Well what if they don't have ES6 support?"
Me: "Thats fine, we've been using a polyfill for years anyways. Please use
includes()"Dev: "I'd rather stick with something I know will work"
Resistance to change comes in many forms
ten24 · 7 points · Posted at 22:33:17 on April 26, 2018 · (Permalink)
And they might be right. How well do you know your users? Software use-cases vary widely. There are most certainly win 9x systems in use today.
Nickolai1989 · 2 points · Posted at 20:43:29 on April 27, 2018 · (Permalink)
But his point isn't that it might break things for win98 users, it's that the code that ostensibly fixes a win98 issue might also, incidentally, be covering a bug that's still active in win10. So by removing it, you'd uncover that.
In which case I'd say the reasonable thing is have a testing environment and/or a set of test criteria by which you evaluate releases.
So to s-mores, I'd say the response would be "let's try taking it out and run some tests on issues that this code could conceivably raise, and if they pass, we'll ship it. If something else comes up, we'll re-introduce it, or better yet find a more robust fix". It's ok if it breaks things, as long as you have a backup plan.
Xaxxon · 1 points · Posted at 23:17:14 on April 26, 2018 · (Permalink)
This is what CI is for. If you don’t have that then the reaction is a good initial reaction.
ValAichi · 8 points · Posted at 19:56:48 on April 26, 2018 · (Permalink)
And then they do comment, but it's in another language so whenever you want to read a comment (or even a variable name) you have to run it through google translate...
anothga · 2 points · Posted at 20:57:02 on April 26, 2018 · (Permalink)
And then Google Translate totally butchers it and you're still confused.
Servalpur · 2 points · Posted at 22:16:39 on April 26, 2018 · (Permalink)
Even more confused than before.
pdp10 · 1 points · Posted at 23:16:46 on April 27, 2018 · (Permalink)
I have a rule that a comment in another language is acceptable when the alternative would have been no comment. Assuming your toolchains can handle UTF-8 in code, that is.
intrepid_i · 1 points · Posted at 16:03:01 on April 28, 2018 · (Permalink)
Ooh interesting. What's it like reading code by someone who obviously speaks a different language?
ValAichi · 2 points · Posted at 16:49:45 on April 28, 2018 · (Permalink)
I was lucky in that it was still in the Latin alphabet.
Overall, not too different to reading uncommitted code; it was ancient legacy code, and that was the main thing I had to struggle with, not the language - which I did run through google translate at points, though it didn't turn out to be very helpful.
Fizzbitch125 · 8 points · Posted at 02:36:12 on April 27, 2018 · (Permalink)
I think that too many people think that when they're told to comment their code they're supposed to describe what the code is doing. And so the balk because, why should they describe what the code is doing, just RTFM! What they don't understand is that the reason you comment code is to describe why it's doing what its doing. So that when you come back in 6 months and go "why the fuck would I do that" you know why. And if you have to make another change you don't revert all the little kludges and fixes
Miserygut · 5 points · Posted at 22:57:19 on April 26, 2018 · (Permalink)
I don't even write comments for other people. I write comments for myself when I inevitably have to go back to a script I wrote n months ago and have completely forgotten whatever esoteric kludge I had to do to get it working. Ah yes the credential passthrough doesn't work on the third Sunday of every month which means the letter 'a' gets dropped from every other sentence in the log file, that's why this fix is there.
I often don't have the luxury of using anything except the framework or library handed to me by the software creator. When it comes to "smelly code" verbose commenting is just part of the deal. I get it working and move on, life's too short.
JohnBooty · 7 points · Posted at 23:04:34 on April 26, 2018 · (Permalink)
I absolutely agree with you. Anybody who can remember why they did every little weird, kludgy, bizarro thing they do is absolutely fooling themselves. I barely remember what I did this morning, let alone 10 months or 10 years ago.
Tom2Die · 3 points · Posted at 09:06:48 on April 27, 2018 · (Permalink)
fwiw I subscribe to that mentality, more or less. My thought is that comments shouldn't need to say "what" code does, but rather should say "why" the code does what it does. I think that the people to whom you refer don't draw that distinction, unfortunately, and just blanket say all comments are bad full stop.
Allways_Wrong · 2 points · Posted at 22:51:17 on April 27, 2018 · (Permalink)
I’ll never understand not commenting at least blocks of code.
Even just:
/* Get data. */
/* Massage it A. */
/* Massage it B. */
/* Turn it into a tree and return. */
Now everyone, especially you, can skim read the code and understand where and what it is doing/supposed to do. And dig further at each section if required.
The comments are practically micro architecture.
But hey, I’m inspired by LEGO instructions.
pdp10 · 2 points · Posted at 23:12:55 on April 27, 2018 · (Permalink)
Ah, the "Uncle Bob Defense". In "Uncle Bob" Martin's Clean Code, it's said that good code usually doesn't need comments because it's written so clearly. In their search for a justification for their aversion to comments, the misguided coder seems to convince themselves that because their code doesn't have comments, it must therefore be good code.
The answer to this fallacy is always Why, not how. That workaround doesn't need a comment telling me how it works, it needs a comment telling me which browser is affected and a link to upstream's bugtracker so we know how to determine when we can delete the workaround.
binford2k · 2 points · Posted at 07:00:06 on April 27, 2018 · (Permalink)
They're not entirely wrong. Only mostly so ;)
The thing that people who think like this are missing is the purpose of comments. You don't need to document what your code is going and you should not; just document why it's doing that.
I can see that you're calculating the square root of the 17th field of the
getEventInfo()return value. But I don't know why. Why's it the 17th field and not the 18th? Am I sure that you didn't make a mistake when choosing the field to use? Where's the API spec that describes what all the fields are?Unless they write method names like
LoadLibraryWrapperForWindows95Support__TODO__RemoveWhenWindows95ReachesEOL(), then their methods are not named descriptively enough to remove the need for explanatory comments.JohnBooty · 3 points · Posted at 07:34:37 on April 27, 2018 · (Permalink)
Yes, that is 100% correct in my experience.
"OBVIOUSLY I'm taking the square root of the 17th field. Any idiot can see that!"
But, y'know... yeah. What you said.
irqlnotdispatchlevel · 2 points · Posted at 19:54:18 on April 27, 2018 · (Permalink)
Those hacks might be for something that's not in your power. For example, we have workarounds for operating system bugs, or for security / maintainance software or for God knows what. Sure, those got fixed, but there is always that one important customer that will not update so that workaround is there forever now.
magnakai · 1 points · Posted at 13:51:47 on April 27, 2018 · (Permalink)
I’ve started sending back PRs if they do something weird and don’t leave a comment. They’ll often have a good reason if I ask why they used a weird solution, but it’s so easy to put that as a comment! In a year’s time they won’t have a clue what that weird bit’s for.
[deleted] · 1 points · Posted at 09:28:03 on September 21, 2018 · (Permalink)
Saved. Kludges can't be avoided entirely and this is good solution.
kbotc · 3 points · Posted at 04:01:24 on April 27, 2018 · (Permalink)
Yea, but once Windows Vista came around the LoadLibrary code now causes a random segfault and requires UAC for almost unexplained reasons: You built up 30 to 40 of these edge cases in the 450 line function and now you need to move forward but are stuck by legacy requirements and they layer on each other. You pull out LoadLibrary, but someone thought it was a good idea to depend on the return value of that somewhere else deep in code "Because performance." Now you have to go back and try and understand a coding methodology that was in vogue 25 years ago. All to support Windows 95.
techno_gold_pack · 17 points · Posted at 18:13:33 on April 26, 2018 · (Permalink)
But sometimes old code does really suck and needs to be thrown away..
mughinn · 10 points · Posted at 18:36:22 on April 26, 2018 · (Permalink)
He addresses this though
the_red_scimitar · 11 points · Posted at 18:59:15 on April 26, 2018 · (Permalink)
Or, it could have been written to maliciously prevent understanding, in an attempt at (unearned) job security. I had this for a consulting client, a major, international electronics manufacturer, who's entire radiation-hardened production process was managed (both technically and administratively) through a huge program written entirely in VB5.
The developer did the following, very intentionally:
Used only single-letter variable names everywhere.
Not one comment anywhere.
No written documentation.
Almost no code factoring. Rather than define subroutines, he just copy/pasted code (one of the reasons it was huge).
And the coup de grâce: he didn't use the visual designer for forms at all. There were no visual elements in the designer for his UI. Instead, he created each UI element in code, and positioned it manually on the page - kind of what the older code-behind stuff did in ASP.NET, but all of this was manual. And remember, only one letter variables, no strong typing, reuse of variable names therefore everywhere, for any type of object at any time.
He was entirely hostile to my project, which was to "fix" it. Luckily, the client agreed to a complete rewrite, which was accomplished along with a full suite of new requirements analyses. user interviews, etc. As it turned out, the system had been so flawed, that almost nobody used it as intended, but minimized contact with it, resulting in unpredictable results in production runs, inability to correct problems, etc. - but then, using the original software apparently didn't make that any better.
Edit: Also, no source code management, no issue tracking of any kind.
mughinn · 6 points · Posted at 19:29:52 on April 26, 2018 · (Permalink)
I think we can agree that that situation is an special case
Psyladine · 1 points · Posted at 18:42:30 on May 1, 2018 · (Permalink)
Security by obscurity is far from the exception.
the_red_scimitar · -1 points · Posted at 20:04:27 on April 26, 2018 · (Permalink)
Certainly is unique in my experience. I've seen some code almost as bad, but due to incompetence rather than design.
[deleted] · 3 points · Posted at 18:57:59 on April 26, 2018 · (Permalink)
[deleted]
mughinn · 14 points · Posted at 19:32:23 on April 26, 2018 · (Permalink)
Joel is not arguing for "Don't rewrite", Joel is arguing "Don't rewrite your entire code at once"
Yes, you can rewrite a part. Yes, you can rewrite to make the UI in graphs instead of spreadsheets. No, don't start from scratch all over again
antiname · 1 points · Posted at 01:33:06 on April 27, 2018 · (Permalink)
So he argues that you should refactor your code instead of rewrite it?
jephthai · 1 points · Posted at 23:16:41 on April 27, 2018 · (Permalink)
I think this is only somewhat true. You can definitely change individual things. But with the inertia of the large codebase, there's only so far from its original architecture that you can walk it until you're talking about the same amount of effort as a rewrite.
I think sometimes a rewrite is a good decision. It shouldn't be a clean-room rewrite though. There should be constant reference to the original code to account for compatibility and so as not to lose valuable things that were in the original code base.
thedr0wranger · 0 points · Posted at 01:27:22 on April 27, 2018 · (Permalink)
I don't see that he's addressing a number of valid reasons to go full rewrite.
My company did a rewrite, it was costly in terms of money, sanity and customer goodwill, but it's the only way there's a decent future for the product. We had a number of factors, among them :
We contracted the trustworthy dev team(and myself, the first internal dev/IT person) to rewrite the application from scratch on new technologies with an eye to supporting the new goals, new use case and new scale. We x'ed out the the bad contractor completely and rewrote their component on a new platform. I'm now the sole dev doing regular work and it's manageable.
We did the work in a summer and had a really rough fall breaking in the new product but by no means would I trade it for the idea of trying to piecemeal change the old application.
I think given the right set of circumstances there really is a case to be made for getting rid of old, obsolete, ill-designed code. Perhaps it's only on the far edge cases, but Spolsky doesn't seem to acknowledge any such thing. Instead he dogmatically asserts that you should slowly creep projects over. If we had done that the new project would be a quivering mass of little links to the old system and we'd have basically all the same problems because the fundamental design was no longer valid.
p1-o2 · 1 points · Posted at 21:10:10 on April 27, 2018 · (Permalink)
I've been through this twice now as you described. That's a case where I'd have fought for a refactor as well. Especially with so much of the team being more familiar with new tooling.
I recently had the joy of trying both ideas out at the same time actually. We had half the team do a full rewrite of the code-base while half the team fixed up the old code. We ended up with two copies of the reworked product in the same amount of time (1 year), but the new code-base was still far more robust even if they were functionally the same.
thedr0wranger · 2 points · Posted at 21:57:12 on April 27, 2018 · (Permalink)
I think not being shackled to assumptions and models that are no longer valid( if they ever were, sometimes the first design was just bad) has a lot of benefits. Moreover designing around new technologies from the start rather than emulating old behavior and then integrating new features is a very different experience. I did both on this project.
p1-o2 · 1 points · Posted at 22:45:58 on April 27, 2018 · (Permalink)
Agreed, thanks for sharing your experiences! And GL down there in the underdark. ;)
thedr0wranger · 2 points · Posted at 23:40:34 on April 27, 2018 · (Permalink)
Heh, sometimes. I forget my username, had me confused for a moment.
I just immediately take a skeptical stance when any person, even one as skilled as Joel Spolsky, makes broad sweeping statements about complex topics, doubly so when they suggest that the least regrettable choice my company has made with our software was some grand snafu.
thedr0wranger · 1 points · Posted at 01:31:45 on April 27, 2018 · (Permalink)
I want to add that without a rewrite we very likely would never have had the buy-in from management to get the appropriate manpower on the job. The idea of a whole new world of possibilities is how we contracted an outside team, trying to part it over would never have gotten the manpower necessary to do it before the product choked and died.
FlyingRhenquest · 1 points · Posted at 22:02:25 on April 26, 2018 · (Permalink)
And when that happens, management's so used to hearing that the code sucks and needs to be thrown away that they'll ignore any valid justifications for doing so.
Polantaris · 177 points · Posted at 15:48:14 on April 26, 2018 · (Permalink)
The idea that just because code is in production means it must work is a logical fallacy. Not all code in production works. Sometimes it's just not reported as a bug. Sometimes people don't realize it's a bug. Sometimes people find workarounds to accomplish what they want without reporting it. Only when none of those things are true do bugs get reported (most of the time).
There's plenty of shit that has gone wrong that people don't even realize is wrong. If you don't know it's wrong, why would you report it?
I worked for a project that one step of it was to edit an existing page on a web application and apply new rules to it. One of the things I decided was better off was to rewrite the whole thing, because it was shit (it was). In the process of researching how it was working to know how to rewrite it, I learned that it never worked right in the first place. It was a request approve/deny system where there was both manual and automated denials (based on different scenarios). All manual approvals and denials were counted as approvals. All of them. Only automated denials ever got treated as denials.
No one ever noticed, because one team approved/denied requests, and a completely separate team handled the results of those approvals/denials, and these teams never coordinated anything. The requesters wouldn't report anything because nothing appeared wrong as the bug always worked out in their favor. So how would anyone ever notice there was a discrepancy? This page was in production in an incorrect state for over ten years.
The point of this story is to prove that this entire concept that, "It's in production and no one complains, so it must be working," is plain wrong. It's very easy for people to not realize something is wrong. No one would have ever caught this bug if I hadn't done a top down analysis to rewrite it.
The important part about refactoring your own code and rewriting it is to know when it's appropriate and when it's not. If a full rewrite is going to give little benefit and take a long time, don't do it. If it's the fifth or sixth time you're doing it, don't do it. If you don't know anything new that would provide benefits at the core of the rewrite, don't do it. But you also have to know what you're doing if you're rewriting it. If you're going to rewrite it by doing something completely different, then it's probably not going to be beneficial unless what you're doing has already been done elsewhere and has been successful.
sevl · 40 points · Posted at 17:33:56 on April 26, 2018 · (Permalink)
if that was in production for ten years and nobody ever had a problem the requirement itself was not needed. during rebuilding the requirement for manual approval should have been reevaluated
Polantaris · 37 points · Posted at 17:40:26 on April 26, 2018 · (Permalink)
The manual approval requirement scenario required a human element and the automated did not, but were two completely different scenarios that would lead to approval with different approval time windows. It was absolutely required.
It was a bug that no one caught because no one did a cross analysis between what the team that was approving requests manually did and what requests were acted on as if they were approved. Everyone assumed that it worked because it was in production. That doesn't make the requirement invalid. It just furthers the idea that "In Production does not mean 100% working".
fiverhoo · 28 points · Posted at 18:00:50 on April 26, 2018 · (Permalink)
The real question, is that after 10 years of working wrong and you fixing it, was there any actual real benefit to the business, in terms of dollars or efficiency, or any other metric you choose.
Or was the requirement met and some manager someplace could check a box.
ebonyseraphim · 15 points · Posted at 20:10:13 on April 26, 2018 · (Permalink)
It's really not that hard to see the problem. No one noticing the problem doesn't mean the problem isn't having a drastic effect. If there were rounding errors to interest, no one would notice it easily. But an audit after 10+ years on something like a mortgage, or savings account, and there would be quite a difference. I really, really hate software teams who lean so heavily on the idea that no complaints means everything is good. I can understand dev work prioritization being somewhat based on active complaints from more important customers, but what managers tend to overlook in these situations is that the unnoticed terrible bug can be noticed at ANY point in time and if/when it does, it'll look worse! Even if I could tolerate an initial release with such a mistake, knowing it's been around for so long with the same dev team also means an engineer or two, or three, has noticed and probably brought it up to a manager who de-prioritized it. That alone would make me stop working with said team if I was on the customer side. It immediately tells me the quality of their engineering.
Polantaris · 33 points · Posted at 18:55:31 on April 26, 2018 · (Permalink)
Actually, yes. The bug fix related directly to payments they shouldn't have been making but were.
The rewrite was going to happen anyway, though. The old page was such a mess it probably would have taken more time to add the new requirements into it than starting from scratch anyway.
jk147 · -1 points · Posted at 18:38:16 on April 26, 2018 · (Permalink)
It may mean more efficiency, but in terms of dollar per benefit def. a no. Creating a whole new thing for an edge case is counterproductive.
Not to mention the possibility (almost certainly) of introducing new bugs with an overhaul.
sevl · 14 points · Posted at 17:57:49 on April 26, 2018 · (Permalink)
so in 10 years there was never a case where an approval was questioned, where someone asked the approver why something was approved where an approver got in trouble for the false approval? there was never any consequence to an approval which should have been a denial? why then would you need the possibility to deny at all?
Polantaris · 16 points · Posted at 18:56:51 on April 26, 2018 · (Permalink)
They didn't question it and just took it for fact, because it was two completely different groups that handled the acceptance/denials vs the group that actually acted on the accepted requests. Since it was two different groups that didn't coordinate at all, no questions about the approved requests were ever raised and they were just assumed as correct.
kntx · -1 points · Posted at 18:56:01 on April 26, 2018 · (Permalink)
Exactly
ill_mango · 3 points · Posted at 18:19:57 on April 26, 2018 · (Permalink)
I think the point isn't that production code definitely "works", but that production code often has had many (potentially undocumented) use cases/bugfixes added to it over time. These use cases are hard to transfer in a rewrite.
Polantaris · 1 points · Posted at 11:55:58 on April 27, 2018 · (Permalink)
That's the point of User Acceptance Testing (UAT). The users will try to use the new version exactly the same as the old one. They know what should or shouldn't work based on the context of the old application combined with the new requirements. If they were able to do something in the past and now they can't (or, were not able to do something and now they can), they'll call it out. If you don't have a good reason for it, you know you missed something.
QA has a purpose in that their job is to make sure that the application is designed the way the requirements say they should be, while UAT's purpose is to make sure that the requirements and resulting application actually fit their real world use cases.
When you're redoing an application, UAT isn't new users, it's users that have been using the old system for as long as possible. That gives them the ability to catch and call out these unknown use cases because they were likely there when they were first implemented and know the reason behind it.
ill_mango · 1 points · Posted at 20:09:06 on April 27, 2018 · (Permalink)
I've never seen a set of UATs that capture ALL cases - there are simply too many use cases to justify detailing each one w/ all possible input combinations.
It sounds like your actual users do UATs, is that true?
Typically I have my product managers run the UATs, because my end users expect any software we release to be fully QA'd. That being said, we do have a beta stability period, where beta users have a chance to report bugs, but even with hundreds of beta testers, I still find that some use cases don't get completely tested.
UATs are supposed to capture all functionality in theory, but in practice I've never seen it happen.
jadero · 1 points · Posted at 21:22:14 on April 26, 2018 · (Permalink)
Most people treat computers as either infallible or useless. Neither attitude will get you good bug reports.
Polantaris · 2 points · Posted at 21:29:22 on April 26, 2018 · (Permalink)
Most of the time you don't even need good bug reports. You just need bug reports in general. If you release something and there are no reports at all you will assume that everything is working as expected. The problem is what you expect and what the user has come to expect may not be the same thing.
jadero · 1 points · Posted at 21:34:02 on April 26, 2018 · (Permalink)
True.
Tasgall · 1 points · Posted at 06:12:39 on April 27, 2018 · (Permalink)
Or just puts a comment on it because they can't change it because it would break code that uses it. My favorite example, I wish I'd saved the link, is a function in the .net api that looks something like,
Yeah, it "works", but it's undeniably bad code.
Pomnom · 0 points · Posted at 16:18:31 on April 26, 2018 · (Permalink)
So then who should be the judge of whether it's a bug or not?
Polantaris · 5 points · Posted at 16:34:55 on April 26, 2018 · (Permalink)
The people who wrote the requirements and set up the use cases for the end product. But no one is infallible, mistakes happen all the time. Explanation of the full requirement may have missed a scenario or the testers may have improperly tested. However, if the result appears to be as expected from a user interaction side, then it won't ever get reported once it hits production. That doesn't mean it's correct, nor does that stop it from being a bug.
Synaps4 · 5 points · Posted at 17:11:23 on April 26, 2018 · (Permalink)
You're arguing manual denials being returned as a "pass" is not broken?
BornOnFeb2nd · 49 points · Posted at 15:45:13 on April 26, 2018 · (Permalink)
Yes, yes, I don't care about the technical details, I just need an estimate from you before the end of the day.
┻━┻︵ヽ(`Д´)ノ︵ ┻━┻
I got dinged before from telling people something wouldn't work the way they wanted and not giving details until asked to explain... this happened enough that I started preemptively explaining the details behind the problem so they'd understand it....and then got dinged for getting too deep into the minutiae.
optomas · 25 points · Posted at 18:50:16 on April 26, 2018 · (Permalink)
"How deep you want to go?"
I ask this a lot.
You can either trust me (If I say it doesn't work like that, it's because I've tried it, probably hundreds of times and watched it fail) or sit through an explanation.
"Yes fluid is relatively incompressible. Do you think this means it is perfectly rigid? Do you want to see the equation for volume loss in relation to pressure? The keyword is 'relatively', not 'incompressible'."
emorrp1 · 8 points · Posted at 22:41:19 on April 26, 2018 · (Permalink)
And glass is clearly a liquid, that's why old church stained windows are thicker at the bottom.
Tasgall · 6 points · Posted at 06:22:17 on April 27, 2018 · (Permalink)
Nope, common misconception - old windows often (not always) have the thick part on the bottom because the person who put it there put the bigger end on the bottom, like ya' do.
Technically, they're an "amorphous solid", but they don't "flow" really slowly like say, pitch (unless you melt it).
emorrp1 · 4 points · Posted at 13:37:26 on April 27, 2018 · (Permalink)
Yay, baited and hooked.
JohnBooty · 1 points · Posted at 19:29:13 on April 26, 2018 · (Permalink)
You should try Scrum! It's so awesome! It's an entire gamefied methodology where you assign random numbers (that sort of represent time estimates) to stuff before you are able to investigate it and actually accurately assess how long it might take!
mcmcc · 127 points · Posted at 14:25:35 on April 26, 2018 · (Permalink)
"If you plan to throw away one, you will throw away two."
mOdQuArK · 72 points · Posted at 15:24:08 on April 26, 2018 · (Permalink)
"If you don't plan on throwing at least one implementation away, then you're a bad planner."
About the only exceptions I've seen is where you know the problem domain so thoroughly that you have already solved everything in it multiple ways, either because of expertise or simple problems.
Anyone who claims it should be done otherwise should be immediately labeled as not knowing what they're talking about & their opinions heavily discounted.
mshm · 39 points · Posted at 16:30:56 on April 26, 2018 · (Permalink)
Managers should plan to throw away code, developers should develop like it's the code to be delivered.
architectzero · 3 points · Posted at 19:05:08 on April 26, 2018 · (Permalink)
Unfortunately, if the developers were to treat what they’re developing as the shippable product, and it is thrown away, then they are typically also thrown away because, fuck those losers that produced the shit we had to throw away! (It was them, not us!)
Then a new team is brought in... and the same mistakes are made all over again, because all of the learning - the actual value produced by the throw away system - was thrown away with the developers.
jboy55 · 5 points · Posted at 19:35:58 on April 26, 2018 · (Permalink)
Typically this ends with bankruptcy of the company as well. But other shades of this are the old team is still there, ‘they’ label their code as legacy and the new team is taught to ignore the old team/code in case the old ways infect the new ways. The new team is often already in the building but was just spectating from the sidelines. And then there was Joe... and Sue and they were in all of my 11am meetings and never said anything until that fateful 3pm Friday meeting when the knives came out....
I mean, there were a lot of edge cases in the old code that need to be respected.
mcmcc · 25 points · Posted at 16:08:13 on April 26, 2018 · (Permalink)
The moral here is that you often miss out on important information if you don't make an honest effort in producing a fully viable implementation.
Proof-of-concepts are great as research tools but they are typically not substitutes for "real" implementations.
StabbyPants · 2 points · Posted at 17:30:12 on April 26, 2018 · (Permalink)
POC is almost always for something like demonstrating the use of a new tool, or exploratory work in applying it to your domain. when i do them, they're deliberately not deliverable, but produce good patterns for using the tech in the actual product
Polantaris · 1 points · Posted at 12:01:17 on April 27, 2018 · (Permalink)
I dunno, the last POC I did was a test to see if a technology switch was going to get us the improved performance we needed on what we were developing. I took the worst performing chunk and rebuilt it in a new technology to see if we would get the desired effect. If I didn't build it fully and honestly, with the intention of it getting released, it's not a true POC for that ideal. Plus, if approved, the entire idea would would become the foundation of the project as we migrated over (the piece in question wouldn't get done a third time), so if the foundation was shit ultimately I would have made things worse.
If a POC is just a, "Look at what we can do with this!" I totally agree, but there are multiple different varieties of POCs.
Xaxxon · 1 points · Posted at 23:25:16 on April 26, 2018 · (Permalink)
Experience simply shifts the threshold of what is too complex to predict.
What designs are just “obvious” because you “know” they will be bottlenecks later vs when to just write the simplest, naive code.
Tasgall · 1 points · Posted at 06:23:44 on April 27, 2018 · (Permalink)
Aka: you've done it before, probably at your old job.
[deleted] · 18 points · Posted at 15:30:24 on April 26, 2018 · (Permalink)
[deleted]
wrincewind · 50 points · Posted at 15:55:07 on April 26, 2018 · (Permalink)
I generalised my solution and nowadays I plan to throw away n+1.
agent-plaid · 13 points · Posted at 16:49:10 on April 26, 2018 · (Permalink)
I plan to throw away
n+know.bhat · 2 points · Posted at 22:19:21 on April 26, 2018 · (Permalink)
I'm working up to throwing away n2 (or maybe I'll find an efficiency somewhere and get that down to n log n).
Tasgall · 1 points · Posted at 06:25:08 on April 27, 2018 · (Permalink)
I just cut to the chase and throw away nn iterations. Can't be too sure.
Cypher121 · 1 points · Posted at 18:57:14 on April 26, 2018 · (Permalink)
I tried that but then I had to throw out null
xkufix · 22 points · Posted at 16:10:51 on April 26, 2018 · (Permalink)
I just delete my old git branch every morning and start again.
vmcreative · 31 points · Posted at 16:24:22 on April 26, 2018 · (Permalink)
I actually just take it a step further and reformat my computer fresh daily. Helps clear my head before work having to reinstall Windows and partition all my drives.
Lost4468 · 19 points · Posted at 17:30:54 on April 26, 2018 · (Permalink)
I shoot myself in the fucking head to remove the data I have on it.
dvlsg · 15 points · Posted at 19:16:07 on April 26, 2018 · (Permalink)
At least you'll be gdpr compliant.
Attila_22 · 1 points · Posted at 19:28:55 on April 26, 2018 · (Permalink)
Windows? Casual.
xeow · 5 points · Posted at 16:06:05 on April 26, 2018 · (Permalink)
If you plan to throw away n, you will throw away n+1. ;-)
FartingWithASmile · 3 points · Posted at 19:05:21 on April 26, 2018 · (Permalink)
This reminds me of someone I was once unlucky enough to work with who said he regarded all his code as temporary and throwaway, because “managers will always make you throw it away before you have a chance to make it good.” So why bother making it good, he reasoned?
I thought he must have been damaged by bad experiences with stupid managers. But no, turned out he was just an idiot.
Worse, once he got some management responsibility he started cancelling other people’s projects at random to “teach” them how the world really works.
hvidgaard · 10 points · Posted at 17:53:19 on April 26, 2018 · (Permalink)
Rewriting is not a unicorn, and often leads to a million of other problems. There is so much knowledge and testing that has gone into making something perform properly in production. I have never experience or heard about a test suite that captures all of this. This will be thrown out the same second you rewrite everything.
What the mantra means is write a prototype that models major components and their interaction. Then you learn a lot and can start over again. This prototype can be made in a fraction of the time needed to complete the project, and it’ll save time at the end. If something is close to production ready it’s not a prototype, and gradual refactoring is preferable.
dsk · 54 points · Posted at 15:29:10 on April 26, 2018 · (Permalink)
This is the exact reason why you should rewrite code only as a last resort, because you won't know what you need the second, third, and fourth time around either. The longer lived your 'first' codebase is the more this fact is underlined.
Worse for you, your original code will have a massive amount of secret (i.e. unspecified) functionality that was implemented as part of bug fixes, maintenance patches, module rewrites, etc. etc. etc. This functionality builds up over years or decades. A clean rewrite guarantees you will fuck things up all over again, partly because you will miss all that 'secret' functionality you didn't know was there, and partly because you will just fuck things up in new and inventive ways - because what makes you think you're any smarter than the guys in your position who wrote the initial code?
And I speak with some experience. Some of my good friends are developer who were involved in a ground-up rewrite of a legacy C++ application (90s era+) in Java. And believe me, they are smart and talented developers writing really technical code. The project took 10 years (10!) and in the end, they didn't even manage to match the feature set of the original. In the meantime, the product completely stalled being in maintenance mode with no major new functionality and fell behind their competitors. The alternative, of course, was not to do a ground-up rewrite but rather update the code incrementally, module by module - with each module released and get battle-tested in production. They agreed.
This is a horror story that is repeated all the time, and developers never learn. They always think they can do it better a second time.
Because it works.
And nobody is arguing against partial rewrites of specific modules. You can do that. It's the ground-up total rewrite that is almost always a total and utter disaster.
Great attitude to have towards utility scripts. Doesn't really apply to applications with hundreds of thousands (millions?) of lines of code, written over years (decades?), and used in production by hundreds of institutions and hundreds of thousands of users.
Trust me, your 'clean, simple code' is going to look like shit to the next guy who comes over or after a few years of bug fixes and maintenance.
glacialthinker · 31 points · Posted at 15:52:47 on April 26, 2018 · (Permalink)
I was looking for a comment like this, and a related point: that practical problems have a lot of subtle complexity, which has been encoded (hopefully) in mature code. A clean rewrite always seems nice because we tend to be ignorant of all the details until we're faced with them one by one.
On the other hand... mature code which has these subtle details (unclear in code, and uncommented, or worse: untrustworthy comments) sucks to work on because it's volatile under changes. This is where the modular rewrites you're suggesting are great, so you can clarify and improve parts of the code while still interacting with the bulk of the system -- and not failing regression testing.
wuphonsreach · 1 points · Posted at 05:58:24 on April 27, 2018 · (Permalink)
And one of the first goals of the refactor should be the minimum to get the code into a state where it can be tested. Then write those tests and start documenting / uncovering your assumptions about how it works now.
That way, when tests break you can decide:
almightySapling · 8 points · Posted at 17:07:35 on April 26, 2018 · (Permalink)
My hubris, duh.
Eridrus · 6 points · Posted at 16:05:34 on April 26, 2018 · (Permalink)
At my last job I did a small-ish (10k LoC) port/rewrite and ran into this, but I was lucky in that it was a service that only did a single thing and had a single JSON=>JSON interface, so it was possible to run logged messages through it and see the discrepancies.
Anyway, I ran into a lot of these edge cases, but one of the things that became clear was that the majority of these edge cases were not actually important and we ended up dropping them in the port.
Doing the actual rewrite wasn't so bad, testing it to ensure it did what we needed took up most of the time.
dsk · 12 points · Posted at 16:10:03 on April 26, 2018 · (Permalink)
I suspect that people who clamour for rewrites in this thread have codebases of that size in mind. The thing is, nothing I argued really applies to projects that small. A rewrite of 10k LoC isn't particularly difficult for dev teams of any size to attempt. So go nuts - rewrite as much as you want.
Things get real hairy when you have applications with hundreds of thousands or millions LoC.
hardolaf · 1 points · Posted at 06:23:51 on April 27, 2018 · (Permalink)
I work in FPGA design engineering. The testbench master controller for one of my designs is a 10k LOC monstrosity that takes in a custom command structure specified by our simulator. It is scary complex and really needs a redesign. But no one will ever do that because it's scary.
[deleted] · 23 points · Posted at 16:16:18 on April 26, 2018 · (Permalink)
Isn't this part of the arrogance (or perhaps, naivete) that the author is describing though?
This idea that "clean, simple code" obviously doesn't have problems because it is clean and simple. When it may very well be missing a myriad of edge cases that it didn't account for at all and the reason the past code is so messy is because it made the very same mistake and had to be added to incrementally, making it less clean and less simple over time, but also more capable of handling circumstances that no one was likely to think of at the offset.
I'm sure this is not always the case, but it seems plausible that it could be the case in some situations.
pewqokrsf · 12 points · Posted at 17:12:29 on April 26, 2018 · (Permalink)
The argument is that you could turn that messy code into something clean by rewriting it, while maintaining functionality.
Sometimes we think one strategy or pattern is the right one to use, and then 6 months later we find out that we absolutely wrong. Rewriting that code with a different approach can simplify a lot of the mess.
Miserygut · 2 points · Posted at 22:59:44 on April 26, 2018 · (Permalink)
Often it can. However justifying business value for refactoring code to be clean, simple code - which is already working in all given situations - is super tough.
[deleted] · 1 points · Posted at 18:52:58 on April 26, 2018 · (Permalink)
It seems the argument of the article though is specifically about business/competition/cost and how much time you can waste in trying to start over from scratch. Rewriting piece by piece, or rewriting completely in your personal time is, I'm sure, a different story.
mindbleach · 11 points · Posted at 15:43:00 on April 26, 2018 · (Permalink)
To build something right, you have to build it twice.
instantiatedObject · 3 points · Posted at 18:27:56 on April 26, 2018 · (Permalink)
why build one when you could build two for twice the price?
lju1977 · 5 points · Posted at 16:34:58 on April 26, 2018 · (Permalink)
Off by one error. You mean three times.
MINIMAN10001 · 44 points · Posted at 15:12:58 on April 26, 2018 · (Permalink)
For 15 years in space station 13 gas defines order of operations were wrong
recursive · 107 points · Posted at 16:04:35 on April 26, 2018 · (Permalink)
For anyone as confused as I was, apparently "Space Station 13" is the name of a role-playing game. "Gas" is the name of something in that game, and "gas defines" are
define-style pre-processor macros in that game related to gas somehow.yes_oui_si_ja · 26 points · Posted at 16:25:01 on April 26, 2018 · (Permalink)
I should have read your comment before diving into a confusing rabbit hole of forums full of insider language.
Unbalanced531 · 21 points · Posted at 19:16:58 on April 26, 2018 · (Permalink)
Rewritten with that in mind (and some context from the link):
In the game Space Station 13, the order of operations used to calculate plasma's burning temperature was wrong for 15 years because of define-statements.
Nicksaurus · 2 points · Posted at 22:47:10 on April 26, 2018 · (Permalink)
And for people like me who couldn't see what the problem was at first:
The macros used to be
#define value a + b, which would simply inserta + bwherever it was used, allowing for other operators in a statement to take precedence over the addition sign. The commit changes them to#define value (a + b)which forcesa + bto be evaluated first in any arithmetic where it's usedBadWombat · -13 points · Posted at 16:20:47 on April 26, 2018 · (Permalink)
defines should be define's.
recursive · 16 points · Posted at 16:22:07 on April 26, 2018 · (Permalink)
It's plural, not possessive.
BadWombat · 2 points · Posted at 16:27:42 on April 26, 2018 · (Permalink)
If it's supposed to be plural and not possessive, the sentence still makes no sense to me.
When I tried reading it as define's, I got it to make sense, since I assume "order of operations" is a property of define in gas.
mshm · 5 points · Posted at 16:37:08 on April 26, 2018 · (Permalink)
It's both, actually. The order of operations of multiple gas defines was wrong, where gas is a modifier of define.
FartingWithASmile · 3 points · Posted at 19:10:45 on April 26, 2018 · (Permalink)
In describing C code, define is used as a noun. “Sorry, I used a define” or “Glad I got rid of those defines at last.”
It’s a preprocessor statement that does a kind of crazy search/replace in the subsequent code, without any observance of the rules of the language, because it’s done before the true language parsing takes place.
recursive · 2 points · Posted at 16:29:14 on April 26, 2018 · (Permalink)
"were" indicates that there are multiple defines.
Kchortu · 5 points · Posted at 16:48:01 on April 26, 2018 · (Permalink)
Seems like it should be plural and possessive then, so defines'
recursive · 1 points · Posted at 17:49:13 on April 26, 2018 · (Permalink)
I can live with this.
BeniBela · 3 points · Posted at 18:45:46 on April 26, 2018 · (Permalink)
Although a game is not really mission critical.
FreePascal has a bug in generic unaligned memory move that was just discovered.
Luckily for x86 a different, more optimized assembly function is used, but on other processors that need correct alignment this breaks everything in every freepascal program for 11 years.
Rndom_Gy_159 · 2 points · Posted at 20:43:02 on April 26, 2018 · (Permalink)
Shouldn't that
1270be1240instead? Is the OP's correction wrong, or do I need to go back to 4th grade?madmaxturbator · 69 points · Posted at 15:12:56 on April 26, 2018 · (Permalink)
Thanks for this comment.
This article, and a few other reasons, are why I stopped reading spolsky.
He’s chock full of strong opinions, but he’s really not grown as an engineering thought leader.
The points you make are totally valid. Countless times we’ve had to dive into systems that have been patched and repatched by various sets of engineers, none of whom has any great sense of ownership over the system. Ie they wrote code with the goal of pushing out the product, not with the intention of building a resilient piece of software.
In every such situation, shortcuts were taken and then patched over, usually with other shortcuts.
Spolsky glibly ignores that this is the actual reason why engineers want a rewrite - a rewrite means they can basically start fresh and actively avoid the mistakes made over many iterations of the system. He’s never been one to rethink his perspectives, looks like after all these years of no longer being in the limelight he still sticks to what he knows.
nimblerabit · 93 points · Posted at 15:19:12 on April 26, 2018 · (Permalink)
You realize this article is almost 20 years old right? I'm not sure criticizing him for not rethinking after all these years is accurate for such an old post.
madmaxturbator · 45 points · Posted at 15:26:20 on April 26, 2018 · (Permalink)
I didn’t realize it’s 20 years old, I missed that. I read the article and thought “well shit same old Joel” haha. My mistake.
Aeolun · 41 points · Posted at 15:33:33 on April 26, 2018 · (Permalink)
It kind of became apparent to me when he referenced Netscape as something newly released :P
madmaxturbator · 74 points · Posted at 15:59:23 on April 26, 2018 · (Permalink)
It’s easier to write articles than to read them I guess :p
AntiauthoritarianNow · 3 points · Posted at 17:46:39 on April 26, 2018 · (Permalink)
Don't worry; he hasn't changed much.
Synaps4 · 8 points · Posted at 17:17:02 on April 26, 2018 · (Permalink)
The irony would be if this discussion causes Joel to rewrite his article.
I would love to see that.
Psyladine · 1 points · Posted at 21:17:39 on April 26, 2018 · (Permalink)
Sounds more like knee-jerk reactions of programmers proving his point; it is easier to write than read, and they'll defend rebuilding a house to move a door.
pavlik_enemy · 3 points · Posted at 19:23:33 on April 26, 2018 · (Permalink)
It was as incorrect 20 years ago as it it is now. There are multiple cases when the code actually sucks. Yes, sometimes what is perceived as bad code is there because there's no obvious way to make it good, it handles obscure edge cases and business rules. But sometimes it's pretty clear that people who wrote the code had no idea how to write good idiomatic code and just banged on it until it kinda worked.
ElGuaco · 1 points · Posted at 17:37:03 on April 26, 2018 · (Permalink)
The fact that he hasn't recanted makes me assume he still believes it.
daV1980 · 55 points · Posted at 15:40:02 on April 26, 2018 · (Permalink)
That is because the product is the goal.
No one else cares how clean and beautiful a piece of code is that has zero users. It's irrelevant.
Code for most purposes isn't written in a vacuum, it's written to provide functionality to someone or something. Pushing down technical debt isn't valuable in itself, it is valuable because you believe paying it down will allow you to deliver more and better value to people.
gpyh · 22 points · Posted at 16:41:36 on April 26, 2018 · (Permalink)
But it does not have zero user. Once you have such a product that you need to maintain and make evolve, every new feature is an uphill battle. Your velocity decreases to the point where your competition is guaranteed to catch up with you; a rewrite is the only viable option.
However I do agree with Joel here: you don't need to rewrite the full product. You can rewrite the most critical parts of it and incrementally make it better.
ZBlackmore · 11 points · Posted at 19:28:59 on April 26, 2018 · (Permalink)
This is a major point in the article and somehow it seems like many top comments are missing it
phySi0 · 1 points · Posted at 13:15:48 on May 10, 2018 · (Permalink)
But someone did make the point that the article is attacking a strawman, anyway, because nobody who advocates for a rewrite says, “let's throw the whole codebase out and start from scratch”, rewriting bits at a time is already what the rewriters are saying.
ZBlackmore · 1 points · Posted at 14:12:32 on May 10, 2018 · (Permalink)
I've heard people say that many times. When I was less experienced I would say that myself too. It's been a while since I read the blog post but I'm pretty sure there are examples major companies making this exact mistake. This is not a strawman. Rewriting bits at a time is what some rewriters are saying but definitely not all of them.
fireflash38 · 7 points · Posted at 16:43:18 on April 26, 2018 · (Permalink)
It's why it's valuable to have 2 major stakeholders in management for a project.
There's many times in the lifetime of a product where you have to decide whether to ship with known bugs, or wait til they're fixed. If you're too heavy on the one side, you're never getting your product to market. If you're too focused on getting features out, you're going to end up with a pile of garbage that takes so much longer to add new features.
As to the article, I feel like people missed the latter half of it. You can maintain and fix stuff without throwing it what exists wholesale. Some of it will be very close to a rewrite. You will re-write parts of the code. But starting completely from scratch? That's just asking for delays after delays.
Polantaris · 2 points · Posted at 12:08:41 on April 27, 2018 · (Permalink)
That's not even close to true.
Clean code is a million times easier to maintain, and "beautiful" code is easier to understand. If I write an hard to maintain piece of shit, when it comes time for a maintenance programmer to come in and fix some bugs, they're going to have a shit time and end up doing the worst thing possible: ineffective workaround. Instead of fixing the code at its core, they handle the result of the broken code. It's a HUGE issue. Any hope of efficiency is thrown out the window right then and there.
Another issue with code that is not easily understood (aka ugly) is when it comes time to update something common or make minor modifications that could benefit everyone, instead of working with what's already there and adapting it for everyone, they will duplicate the entire file, make their changes, and apply it only to their work because that's the only way they can ensure it doesn't break something (as everything else is too complicated for them to be sure it's doing what it should be). This results in tens to hundreds of files that are identical except for minor pokes and prods in different locations. As someone who came on to a project late with a fuckton of this, this is a nightmare to figure out, maintain, and above all else, fix. It makes matters a hundred times worse.
Clean and beautiful code has a purpose, a long term purpose. As long as you don't overdo it and spend way too much time on it.
sirvesa · -2 points · Posted at 15:51:31 on April 26, 2018 · (Permalink)
I'd upvote this more than once if I could
balefrost · 19 points · Posted at 15:20:42 on April 26, 2018 · (Permalink)
To be fair, this article is 18 years old. He may very well have grown in the following (nearly) two decades.
Synaps4 · 5 points · Posted at 17:18:05 on April 26, 2018 · (Permalink)
....its about time for Joel to rewrite this article, imo. :D
blasto_blastocyst · 3 points · Posted at 20:03:01 on April 26, 2018 · (Permalink)
We'll just refactor it by changing "Netscape" to "MySpace"
madmaxturbator · 4 points · Posted at 15:25:35 on April 26, 2018 · (Permalink)
Oops I didn’t see that! Makes more sense then :) after reading it I thought “this is the same old spolsky” haha
RagingAnemone · 6 points · Posted at 15:29:54 on April 26, 2018 · (Permalink)
The problem with this is if all the patches are shortcuts, what makes you think a rewrite won’t be filled with shortcuts?
original_evanator · 2 points · Posted at 17:56:23 on April 26, 2018 · (Permalink)
But he doesn't ignore it. He challenges the assertion that version 2 will magically be mistake-free; that the reduction of mistakes/improvements will be worth the opportunity cost of the rewrite.
Put another way, yes, a lot of code/systems are so costly to maintain that a rewrite is called for, but it's less often the case than many engineers think.
__j_random_hacker · 1 points · Posted at 19:58:56 on April 26, 2018 · (Permalink)
It's an actual reason, and you're right to say that Joel ignores it, and his article is the weaker for it. But I can't accept your claim that it's the actual reason -- that's just as unhelpfully black-and-white as Joel's statement.
The reality is that it is some combination of the sound reasons you give, and the naive or self-serving reasons Joel gives, that produces any rewrite decision. It's not always easy to gauge how much of each component there is, and there's very often significant amounts of each.
TheCoelacanth · 11 points · Posted at 15:54:35 on April 26, 2018 · (Permalink)
Yeah, he's completely misinterpreting the mantra. You're supposed to build one and throw it away immediately once you understand the domain, not maintain and use it for years accumulating a bunch of domain knowledge in the code and then throw away all of that and build a new version with people who didn't build the original version.
boot20 · 4 points · Posted at 17:58:31 on April 26, 2018 · (Permalink)
Well, that and the perception that those coders didn't know what they were doing and I'm a better coder.
Many times the older system is fine it's just a massive pain in the ass to get into somebody's mind and figure out why they made certain decisions.
LetsGoHawks · 9 points · Posted at 17:15:44 on April 26, 2018 · (Permalink)
We sure do. And the odds of the fancy new rewrite being that "clean, simple code" that everybody loves? Not good.
I mean, not for the coders of r/Programming of course. We're all amazeballs and write perfect code every time. Just ask us. But for everybody else, the odds are not good.
pavlik_enemy · 1 points · Posted at 19:28:14 on April 26, 2018 · (Permalink)
It depends. I've seen basic CRUD web applications written by people who didn't care to learn the idiomatic way to code with the chosen language and framework. Rewrite made them way better.
erikerikerik · 3 points · Posted at 16:12:25 on April 26, 2018 · (Permalink)
As a graphic designer I can tell you when I worked at big...HUGE online company the amount of “gross looking,” code was amazing.
Programmers would say “I don’t need to comment if the code is clean enough.”
This is true, but after 500k lines of code and backwards patches it all looks like spaghetti.
And old programmer once told me “I don’t need to debug because I read my code.” Same man told me to “make your code read like a novel, not a medical essay.”
I can go back to my old macromrdia / Visual Basic files and figure out what I was thinking back in 1997...
adelie42 · 3 points · Posted at 16:34:04 on April 26, 2018 · (Permalink)
The other side of this is, "don't let perfection be the enemy of good".
As a novice I've made great progress taking this to heart. Writing ANYTHING is better than staring at a blank screen waiting for divine inspiration that will command your hands to write perfect code the first time around. It not it doesn't work that way, it can't.
I've even gone as far as intentionally writing a module incorrectly because I can't think of the right way. At some point, maybe hundreds of lines in, that conception of the problem domain will hit and it will suddenly become clear what I am supposed to be doing.
But I never would have gotten there without willingness to do it wrong first.
THEN, on the occasion I come up with a well designed object, I'll import them into new projects. That's where I can appreciate "don't throw away old code", but that "old code" is the survivor among many many versions that were thrown away.
Don't reinvent the wheel, and yet nobody is driving around on stone carved tires.
wuphonsreach · 2 points · Posted at 06:07:45 on April 27, 2018 · (Permalink)
We recently fired a developer who could not get past this concept. They would spend days trying to understand the entire code base before writing a single line of code.
We couldn't get it into their head that putting up a pull request that doesn't work and may miss the mark entirely, is a good way to start a conversation. (Our environment requires all PRs be reviewed and merged by a 2nd developer.)
In the meantime, the less experienced junior has pushed out three or four PRs for different issues, had them reviewed by a more experienced developer. The junior/senior talk about what was wrong / misunderstood / unclear, the junior fixes it. Maybe it takes a few go-rounds if it's a tricky or new concept. But the junior is learning from their mistakes and gaining ground. After a few months to a year, the junior needs less hand-holding.
The other person? Hired as a senior and just never produced anything of value.
adelie42 · 1 points · Posted at 14:07:01 on April 27, 2018 · (Permalink)
That is very motivating. There is an open source project I want to contribute to, and I think I am actually starting to understand it. At first it made no sense, but then I started thinking about how I would design the project from scratch and the next time I looked at the existing project it appeared it was designed much the way I imagined it should be.
I am at a loss for what part of the unwritten code I should grab onto and tackle, but I can tell that I am intimidated by the idea of submitting less than some massive amount of perfect code (it is am implied requirement in the README).
Separating those two things will let me take a step forward. I need to take my own advice. Thank you :l
PC__LOAD__LETTER · 2 points · Posted at 16:26:16 on April 26, 2018 · (Permalink)
More likely is that it does have problems, but doesn’t look like it because it hasn’t been exposed to the patchwork of edgecases that inevitably haven’t been accounted for yet. That is, the code could look deceptively simple.
I agree though, the tendency is to throw the old shit away and re-learn what’s actually necessary. I’ve done this many times and will in the future.
duckandcover · 2 points · Posted at 17:42:03 on April 26, 2018 · (Permalink)
OOP requires you to understand the innate structure before you code but, in particular with alg dev with a quick turn around time, very often you don't really understand the structure until its way too late at which point you know that it will have to be restructured because the current system's mismatch with the innate structure makes weird spaghetti hack code that is simply unmaintainable or extendable.
judgej2 · 2 points · Posted at 18:01:16 on April 26, 2018 · (Permalink)
The first time you build the application, you don't know what you are doing. The second time you build the application, you don't know half of what you did the first time.
lenswipe · 2 points · Posted at 21:10:30 on April 26, 2018 · (Permalink)
I worked on a system like this at my last job. It was a two part (cr)application. There was an API client and server. Neither of them used off-the-shelf OAuth libraries, instead a non-standards-compliant OAuth server and client were hacked together whilst apparently high on bath salts. One of the more interesting quirks of this was that you couldn't make requests with nested maps.
This was fine:
This was not fine:
The result of that would be that the value would be evaluated as
Array(PHP array to string conversion). This would then cause the signature strings not to match which would eventually cause the API client (there was only one when this shit show was created) to display the very helpful debugging message ofError: (no data). Interestingly, sending0or empty string as a value would cause this too(I thinkhttp_build_querystripped them out).That was one of many many horrific things in that app. We also had endpoints that were named things like
getGroupOfUsersForAdministrationMenuor whatever. Some API endpoints would return an array of users objects with varying properties. Some would return an array of integers that would be looped over to recover the objects by the client, some would return a pipe delimited string. On error, some API endpoints would return a JSON object{"error": "User is not authorised to perform this action"}some would just return an empty string and some would return nothing and just expect you to figure it the fuck out from the HTTP status code. Similarly, it wasn't uncommon to get an API error object like that served up with the status code200 OK. If you requested all records matching<criteria>, instead of 200 and an empty array, the API would return a string (not even in an object sometimes, just a raw string) with a message along the lines of "No users could not be found matching your search" (yes, really!). This cheerful message would then be served up with a 404 status code which would be detected by the client.Basically, the API reeked of something that was developed in parity with that one client and only that client.
Changing anything anywhere could have unpredictable disastrous consequences. Changing something as benign as the ordering of a list of records from an API controller could potentially cause a huge production failure preventing people from logging in (all with the helpful error message of
Error: (no data)..or sometimes just an empty string which to me always seemed like the PHP interpreter saying "GL;HF".Myself and a colleague inherited this horrific Rube Goldberg machine of a web app from the original dev who was off long-term sick after an accident. Despite my constant warnings of how bad things were, my warnings were ignored until we went live and replaced our clunky-but-working system with the new shiny-but-shitty system. We were expected to continue to just add features, add features and add features onto this horrible doner kebab of an application.
-Developing any feature or fixing any bug was like playing russian roulette. You might be able to deploy the bugfix fine, but you may also completely obliterate production because you changing the format of the person's name was somehow depended on by the permissions system and now everyone is an admin. Every deployment shortened your odds like bullets in a revolver.
eartburm · 2 points · Posted at 15:51:01 on April 26, 2018 · (Permalink)
Of course, building one to throw away can lead straight into the second system effect.
megamanxoxo · 3 points · Posted at 16:08:05 on April 26, 2018 · (Permalink)
I'm a seasoned software engineer. Most the code I write is so freakin maintainable it is ridiculous. Clean code.. external run shell script, easy to read Dockerfile, clear setup and maintenance instruction in a README, automation deployment via Jenkinsfile.. and so much more. Any engineer that comes on board can look at my git repos and immediately be productive because they have containers to stand up their env, run scripts to turnkey everything, and clean code that helps understand the core source as well as the deployment and environment.
I almost never see anything like the effort I put into my repos.. it seems most dev teams are told to build something fast, not build something right. Then managers and C-levels wonder and get frustrated when the new team of developers want to nuke everything and start afresh.
pewqokrsf · 2 points · Posted at 17:10:18 on April 26, 2018 · (Permalink)
Im in the same boat.
Most software engineers are not in love with their work. They do it because it pays well and they get to go home at the end if the day and they don't care about the garbage job they've been doing.
manuscelerdei · 1 points · Posted at 16:19:42 on April 26, 2018 · (Permalink)
Yep. It takes three tries.
First you make an implementation to learn about the problem space.
Second, you make an implementation to understand the best programming patterns to use.
Third try is done using that understanding.
mywan · 1 points · Posted at 16:21:31 on April 26, 2018 · (Permalink)
I only program for personal use and I always throw away the original program intended for a particular functional purpose. Often before ever even finishing the program. As I'm developing the various functional parts I tend to throw those functional parts together in an ad hocish manner. But once I have the functional parts working together I can better plan the overall program flow and think about improvement in the code explicitly intended to improve overall operability. Something I couldn't plan originally not knowing how the functional parts were going to be implemented.
trowawayatwork · 1 points · Posted at 17:58:23 on April 26, 2018 · (Permalink)
What you say makes sense but you kind of say that everyone writes shitty code and you can only get good code by throwing old code away and writing from scratch. How about you read the good old Joel on technology blog post and refactor your post.
peenoid · 1 points · Posted at 18:33:42 on April 26, 2018 · (Permalink)
There's truth to what you're saying.
At the same time, if the decision to rewrite software is being made by the same people or the same type of process that led to the decision to rewrite it, then you're probably not better off rewriting it. Certain presumptions rest on the notion that the second time around will be better just because we "know" more. Those presumptions are impossible to quantify and risky to rely on.
In my mind, only if something significant has changed--better talent, different technology, better process--should you undertake the rewrite of a working system. Otherwise, best case scenario, you'll end up where you are now once again very soon.
unitsofwhat · 1 points · Posted at 19:19:34 on April 26, 2018 · (Permalink)
Came in from /all.
Work in R&D in the manufacturing industry.
This is 100% true for my line of work as well.
If only I could get the VP to understand that....
Gotebe · 1 points · Posted at 19:54:43 on April 26, 2018 · (Permalink)
The bigger point about the second system, though, is that people wanting to make it don't know what they are doing either!
The original developers are gone, documentation is everywhere and/or nowhere and users are spread all around.
otakuman · 1 points · Posted at 19:57:53 on April 26, 2018 · (Permalink)
I think the issue is not that old code doesn't work; rather, that the requirements change, and now you're struggling to adapt an old and possibly flawed system to do more and more things it wasn't designed for.
4609203 · 1 points · Posted at 20:53:31 on April 26, 2018 · (Permalink)
TLDR?
piewarmer · 1 points · Posted at 22:41:29 on April 26, 2018 · (Permalink)
As someone who has only just started learning programming, I can already see this happening even with the really basic beginner code I am writing.
With my first couple of assignments I will plan it out, and have a go at coding the algorithm. If it doesn't quite work as intended, it takes longer to fix what's there then start again
m50d · 1 points · Posted at 09:52:09 on April 27, 2018 · (Permalink)
This is the missing link that reconciles these two positions. I believe Brooks explicitly stepped away from the "throw away" phrasing in later years, as it became apparent that continuous improvements to a working prototype/MVP are a more effective way to reach a good design than restarting from scratch.
irqlnotdispatchlevel · 1 points · Posted at 19:46:40 on April 27, 2018 · (Permalink)
I understand where you're coming from. And going from version 1 to version 2 means that you need to completely reimplement some things.
But here's the trick: you don't throw away the old product. You keep it, you maintain it, and maybe you even backport some features while the new one is in development. You never forget completely about the old code base.
And the actual test of time is not represented by your test suite, it's represented by your customers. Having good feedback and error reporting systems in place is a must for large scale software.
tactics · 0 points · Posted at 16:09:48 on April 26, 2018 · (Permalink)
To follow up on this point:
If you tried to apply the same reasoning to the human body, you'd be patently wrong. An older body (not of code) will be stronger than a younger one... but only to a point. On average, the body is strongest when you're in your mid to late twenties, and after that, it starts a gradual decline to the point that even a young child often has more ability than someone elderly.
Entropy will always win in the end. The young (both people and codebases) are those who have been affected by it the least.
thegreatgazoo · 79 points · Posted at 14:42:04 on April 26, 2018 · (Permalink)
It depends. I've been on many projects where the initial project requirements were "Oh, it's easy, you just need to do A->B->C->D".
Then you hit testing, or worse production, and then all kinds of wackadoo requirements materialize. "Well yeah, Most of the time you do A->B, but in these 3 situations you go to C, then back to B, then to D for 2 of them and C for the 3rd one." "Oh yeah, this other situation requires you to go to E, then spin a D20 and decide to go to B or C or end it in F". <time passes with more of this going on> Oh yeah, we don't do the B->Q->M on 3rd Tuesdays anymore, now it is B->R->E on 2nd Thursdays...
Last year I finally was able to fix one of those that had been going on for 10 years because I refused to directly translate the logic between languages during an upgrade.
rageingnonsense · 38 points · Posted at 19:24:44 on April 26, 2018 · (Permalink)
This is a reality of software though; business requirements change all the time, and it WILL cause inconsistencies in the code. Its just impossible to account for anything that may change. The best you can do is design stuff to be as modular as possible (but within reason); write clean, well formatted code; and comment thoroughly.
None of that "I write self documenting code" bullshit I hear people say. No you don't. You think you do, but you don't. Write some comments.
salbris · 6 points · Posted at 21:28:05 on April 26, 2018 · (Permalink)
My general practice for commenting is to go ham when it's business logic but hold of when it's very simple utilities. Generally it's only warranted when the code is complex.
thegreatgazoo · 1 points · Posted at 00:43:41 on April 27, 2018 · (Permalink)
Sure, requirements change. In this case it was a customer who didn’t know what they needed, a sales guy who wanted a sale, and management just wanted revenue while I ended up with it 3rd hand with zero docs.
rageingnonsense · 1 points · Posted at 00:55:39 on April 27, 2018 · (Permalink)
Sounds about par for the course. There has to be a better way.
SamSibbens · 0 points · Posted at 20:49:59 on April 26, 2018 · (Permalink)
That's what happened when I designed the menu for my game.
Bl00dsoul · 505 points · Posted at 13:30:44 on April 26, 2018 · (Permalink)
While he makes some valid points, sometimes the codebase is just bad.
A tangled mess of rushed spaghetti code full of "TODO" and "FIXME", and lots of temporary hacks.
At that point starting from scratch can be the right decision, sometimes.
ElGuaco · 155 points · Posted at 15:34:07 on April 26, 2018 · (Permalink)
People who are skeptical of this have probably never worked with a truly terrible code base. I think Joel is right about this in most cases, but there are always those cases that prove exception instead of the rule.
I once dealt with a codebase put together in ad hoc fashion by researchers who had no idea how to code properly and it was the very definition of tightly couple spaghetti code. Every time we needed to add a new feature it took weeks or even months to do it because it took so long to figure out how to shoe-horn in the new functionality without breaking everything else.
Finally, we got permission to prototype a version 2.0 that used good OOP, dependency injection, and unit testing and we modernized using RESTful services instead of SOAP. We had a working version in a few weeks(!) and fully replaced the old version within a few months while adding new features that had been on the wish list for years. This was no simple app, but a series of applications and web services and a large database.
Sometimes, you just have to acknowledge the fact that existing software is just bad and time spent fixing it is better spent on a replacement.
149244179 · 83 points · Posted at 17:20:22 on April 26, 2018 · (Permalink)
I had a job where there were a dozen+ 30,000 line long classes. Not files, classes. There was a Globals file with ~2,400 variables in it. Every class basically stored its own copy of the system state. Previous developers would copy paste entire functions and change 1-2 lines instead of adding an "if" or parameter to add/change functionality. Every parameter (and global) was "Object" or "Arraylist" - nothing strongly typed, everything used late-binding. This was all in C#, so its not due to some cryptic language requirements.
Needless to say it nearly impossible to fix a bug without breaking something else. Over time most of it was simply tossed and rewritten because rewriting large chunks of the program was easier than changing a few lines.
a_blue_ducks · 12 points · Posted at 18:24:47 on April 26, 2018 · (Permalink)
Man that sounds awful. I wish there was a way to see a company's code before joining them lol
Attila_22 · 21 points · Posted at 19:44:48 on April 26, 2018 · (Permalink)
The stuff of nightmares
[deleted] · 10 points · Posted at 23:03:29 on April 26, 2018 · (Permalink)
That is definitely not real.
as-opposed-to · 0 points · Posted at 22:50:00 on April 26, 2018 · (Permalink)
As opposed to?
ElGuaco · 14 points · Posted at 17:33:17 on April 26, 2018 · (Permalink)
At my current job, there is a core class that does a huge chunk of processing. The main method is over 10,000 lines long and has dozens of GOTOs. In C# with no unit tests. Several attempts have been made to refactor this class and all have failed.
maxdifficulty · 30 points · Posted at 18:22:54 on April 26, 2018 · (Permalink)
GOTOs in C#? Kill it with fire.
wuphonsreach · 2 points · Posted at 06:10:41 on April 27, 2018 · (Permalink)
Yeah, you need to figure out some way to break that monstrosity down and start creating tests for behavior. Even chipping away at it in small pieces can work (starting with the innermost loop / block).
hardolaf · 2 points · Posted at 06:32:50 on April 27, 2018 · (Permalink)
That sounds like attempts to rewrite "hardware gospel" also known as the "magic sauce from the designers that make everything work". Never change "hardware gospel". Every time someone does, shit breaks bad. It's the only type of code in the Linux kernel that is allowed to break their strict coding guidelines because sometimes, they have to break the guidelines to make it work.
One PCIe device that I worked on needs data written to a certain location starting on a 3 and 3/4ths byte boundary without \a write of the lower 3 and 3/4ths byte. Why? I don't really know. It's some bug in some third-party IP Core in my design. So I had to write hardware gospel for the software team to force the Linux kernel to send a malformed TLP capable of writing starting at that offset.
OverflowingSarcasm · 5 points · Posted at 09:46:26 on April 27, 2018 · (Permalink)
I've worked in a codebase that had
foo.h,foo.cpp,foo_2.cpp,foo_3.cppandfoo_4.cpp. I asked why there were four separate files for implementing the one class, and I was told by the author of the code (and also the owner of the company) that the IDE can't handle that much code in a single file, so he just makes a new file every time the IDE stops working.phySi0 · 1 points · Posted at 13:32:14 on May 10, 2018 · (Permalink)
Whilst duplication like that is hardly desirable, your proposed solution is not a great one.
https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction
some_grape · 0 points · Posted at 21:59:37 on April 26, 2018 · (Permalink)
Honestly, my VEX robot has 12k lines and I didn't even consider it that long. I'm really not trying to be r/iamverysmart but it's been a year long process, and that's only part time, I'm willing to awnser questions. It's written in robotc, so I'm not sure how that translates.
149244179 · 2 points · Posted at 22:58:18 on April 26, 2018 · (Permalink)
If a project will only ever have 1 developer working in it, it does not matter that much. You wrote the code, thus (hopefully) you understand it. I am guessing all 12,000 lines are not in one giant file/function as well.
When you have a team of 10+ people working on the same codebase, standards become more necessary.
The codebase I was referring to was a safety critical (humans could die if things go wrong) application with ~450,000 lines of code. I don’t know how they passed certification in the first place with their garbage code.
some_grape · 1 points · Posted at 23:02:20 on April 26, 2018 · (Permalink)
Well, that's where your wrong buckaroo it is one file, mostly because the development software is a little sketchy on including files sometimes. And yeah, I know my robot is a little different and easier to manage, but I just wanted to say 12k lines isn't that much.
Dead_Lizard · 1 points · Posted at 22:31:44 on April 26, 2018 · (Permalink)
Why are you using robotc and not pros?
some_grape · 1 points · Posted at 22:34:19 on April 26, 2018 · (Permalink)
Personally, because I have so much of a codebase built up it's hard to transfer over to pros, and it's just what I'm used to. Plus speaker functions :)
Dead_Lizard · 2 points · Posted at 02:30:43 on April 27, 2018 · (Permalink)
Gotcha, well I highly recommend switching to pros when v5 comes out! Nice to meet a fellow vexxer here on Reddit!
LainIwakura · 29 points · Posted at 19:50:49 on April 26, 2018 · (Permalink)
I'll share some quick stats on the code base I currently work on...we're currently trying to rewrite it from scratch because it really is bad.
1) Most things are classic ASP / VBScript. A few years ago I got permission to upgrade some pages to WebForms
2) They never said no to any customer request no matter how inane. If a customer wanted some text label to be red there would be a switch case based on the account code to implement this functionality. When customers left these dead code paths were never cleaned up. This has led to honest to god switch cases thousands of lines long in some places to simply display a different image with different dimensions based on whatever customer is logged in.
3) Database never had any sort of design, giant tables with columns like col1, col2, col3, all the way up to 60. Terms like "One-to-many" were completely foreign to the original team. I don't think there are ANY foreign keys.
4) Every file was in the root directory except for the few things they opted to make into "libraries", and the naming scheme was some arcane thing involving roman numerals that no one understood. If it had any purpose the meaning has been long lost.
5) Custom encryption that was basically some XOR magic. Thankfully this has been replaced.
6) No classes or complex types (lists, dictionaries). All arrays are basically magic...you end up with things like:
etc., very simple example - it gets much worse once they start doing any arithmetic with the indexes. Oh, and they also decided to have the indexes start at 1 even though VBScript actually has 0 based indexing. Due to the hardcoded nature of the arrays adding anything is a pain and heaven forbid you want to remove something in the middle.
7) Type confusion everywhere. Cstr/Clng/Cbl on everything - even if you're pretty sure it's an integer. This is because you can't actually be sure it's an integer.
8) There are background 'processors' that handle tasks that would take too long to run in a webpage - okay fine. But they're ASP pages that run in fucking IE. Yes, the background server processing stuff has a dependency on INTERNET EXPLORER. They do log to the screen but it's hardly useful because the page refreshes every 5-30 seconds.
I could go on, and on, and on but I'll just leave it...I couldn't design a worse system if I was trying to do so. It's beyond bonkers.
Medicalizawhat · 3 points · Posted at 06:24:28 on April 27, 2018 · (Permalink)
Fuck that I'd just leave.
LainIwakura · 1 points · Posted at 14:54:18 on April 27, 2018 · (Permalink)
lol that's gonna happen...have to hold out a few more months to get things in order but yeah they'd need easily 10+ more staff in various roles to get anything real done.
pdp10 · 4 points · Posted at 23:33:16 on April 27, 2018 · (Permalink)
Ah, the surprise "white label" requirement. That one can be rough.
GetOffMyLawn_ · 10 points · Posted at 19:40:33 on April 26, 2018 · (Permalink)
I used to work with engineers who were fond of one letter or two letter variable names. And no comments. And couldn't understand why people thought their code was shit.
zuchuss · 3 points · Posted at 22:57:42 on April 26, 2018 · (Permalink)
Like actual engineers or software "engineers" ?
GetOffMyLawn_ · 2 points · Posted at 22:58:34 on April 26, 2018 · (Permalink)
Actual engineers.
zuchuss · 1 points · Posted at 23:23:52 on April 26, 2018 · (Permalink)
If only they listened to those who post on reddit all day. Then the code would be kickin' rad.
pdp10 · 2 points · Posted at 23:34:54 on April 27, 2018 · (Permalink)
It should be noted that i, j, and k are highly traditional iterators, but most people wouldn't complaint about iterators.
pavlik_enemy · 3 points · Posted at 19:31:26 on April 26, 2018 · (Permalink)
Oh, researchers. They are smart, stubborn and don't really care about programming. I think the worst codebases I've seen were produced by them.
BaPef · 5 points · Posted at 19:57:44 on April 26, 2018 · (Permalink)
I worked on a financial system that was built by an accountant with no development experience. It processed $600k a month and only during an audit did they realize it wasn't saving the signed loan agreements but rather regenerating it every time someone viewed it, for 14 years this happened and then when investors wanted all the contracts to review they requested we back generate all the signed contracts which is technically fraudulent.
I_Am_Jams · 2 points · Posted at 22:13:31 on April 26, 2018 · (Permalink)
So much this. There is absolutely a point where code should be thrown out.
Sadly my boss sides with Joel. I once had to estimate a project and it would have been absolutely easier to rewrite (literally half the time), but the boss told the Netscape story and I was told to deal with it.
[deleted] · 1 points · Posted at 09:07:26 on April 27, 2018 · (Permalink)
Jesus christ that sounds like some hellhole any junior developer would press the resign button so quickly.
grauenwolf · 69 points · Posted at 14:19:54 on April 26, 2018 · (Permalink)
The solution to the TODO problem is to replace them all with task numbers from your bug tracking software. That way you can explain what exactly needs to be done and it actually gets added to the priority list.
amineahd · 12 points · Posted at 14:51:26 on April 26, 2018 · (Permalink)
And then you have managers who count productivity and success by the number of open tickets and will try to close as much as possible of these tickets to look good
grauenwolf · 15 points · Posted at 15:03:05 on April 26, 2018 · (Permalink)
I can't fix stupid, however hard I try.
ccb621 · 11 points · Posted at 14:30:00 on April 26, 2018 · (Permalink)
Creating tasks definitely helps you account for the problems, but it’s not a guarantee that said tasks get prioritized. Many teams tend to be more product-oriented, and focused on delivering new functionality, so small fixes don’t get prioritized.
grauenwolf · 16 points · Posted at 15:06:42 on April 26, 2018 · (Permalink)
A priority of "just after hell thaws" is still a priority.
Alternately, when you see the task number in some code you are changing anyways, you can use that as a justification to make both changes at the same time.
[deleted] · 52 points · Posted at 14:29:55 on April 26, 2018 · (Permalink)
I feel that a superior option is to just delete the comments and forget about them.
If they describe really important actual todos, then they're already in the tracking software.
NewW0rld · 60 points · Posted at 14:35:11 on April 26, 2018 · (Permalink)
The advantage of keeping them in the comments is when you go to modify or refactor that section of code, you will take the ticket into account. Perhaps that ticket is about technical debt which you can easily do along with your intended change.
Additionally, if a bit of code has a bug attached or a FIXME, or XXX, when you're debugging a problem, or you just change that section of the code, and you come across the ticket link you will be informed of this critical information. Instead of figuiring out the problem all over again afresh.
grauenwolf · 8 points · Posted at 15:05:45 on April 26, 2018 · (Permalink)
So when it is time to fix that ticket, how do you know where in the code to make the change?
Originally my suggestion was just to get TODO's under control. But now I actively sprinkle task numbers in the code as bookmarks for what needs to be changed during new feature development.
kons_t · 2 points · Posted at 17:33:52 on April 26, 2018 · (Permalink)
When you want to fix a TODO, you grep the code for the bug number.
grauenwolf · 2 points · Posted at 17:44:32 on April 26, 2018 · (Permalink)
Yep. Saves a lot of time.
yerfatma · 10 points · Posted at 14:55:32 on April 26, 2018 · (Permalink)
Agreed: I recently said to a younger coworker, "I think of my
TODOs as notes to a better, more conscientious me."warped-coder · 1 points · Posted at 22:59:36 on April 26, 2018 · (Permalink)
More importantly other than a few exceptions comments belong to commit messages. They mark not just a code location but a time and piece of work they were done for. Any decent scm gives you the blame tool through you can see the info tied to a line of code.
nickiter · 3 points · Posted at 18:32:34 on April 26, 2018 · (Permalink)
IDK if this is a default feature, but one of my coworkers convinced VSTS to search an entire legacy codebase for "TODO" and similar and create issues for each occurrence (there was no issue tracker before we got there). I thought that was pretty clever.
grauenwolf · 1 points · Posted at 18:41:29 on April 26, 2018 · (Permalink)
Neat trick.
oromier · 1 points · Posted at 14:47:21 on April 26, 2018 · (Permalink)
One of the best advices I've read in a while.
m50d · 31 points · Posted at 14:31:52 on April 26, 2018 · (Permalink)
I've found that even then, it's better to rewrite the codebases a bit at a time, and keep it functional the whole time. (The same principle applies all the way down: whenever I think "I'll just refactor everything in one go, it'll be quicker that way" and go into a 2-day dive I end up regretting it, it's better to make a series of 10-minute changes and rebuild and test each time, even if that means I end up doing multiple passes over the same code).
42egrees_south · 5 points · Posted at 15:39:26 on April 26, 2018 · (Permalink)
totes agree, I take the approach of building the replacement code in parallel and then cutting over the tests (if any) and functionality.
I think a lot of software rot would be helped by regular change management practices, and not like change control for releases, but looking a the dumpster fire of a code base and then deciding on how to get from point a to z in a structured way with no downtime.
ops people are better at this in some regard.
m50d · 6 points · Posted at 16:11:36 on April 26, 2018 · (Permalink)
That's not what I'm advocating at all. I find it much better to improve the existing code in-place.
I find that all you need is the freedom to make small improvements every time you work on a code area. Point z is rarely where you actually want to go - by the time you get to point m you'll have a much better idea - so making a structured plan ahead of time is often actively harmful.
blackholesinthesky · 2 points · Posted at 20:22:32 on April 26, 2018 · (Permalink)
If you're versioning and deploying correctly your users should never experience any breakage regardless of which approach you take.
m50d · 2 points · Posted at 21:01:37 on April 26, 2018 · (Permalink)
True but beside the point.
FlyingRhenquest · 193 points · Posted at 13:47:38 on April 26, 2018 · (Permalink)
Yes yes and you think "Oh, I could do this way better!" Then you start writing it and you make all the same mistakes they did originally and the bug reports and feature requests start rolling in. Then before you know it, your code is a tangled mess of TODOs and FIXMEs.
Back in the '90's, I worked with a company that had licensed the AT&T UNIX source. A coworker was poking around in the vi source code and found a comment from 1970 complaining that the original programmer didn't like some bit of terminal handling that was going on, and he'd made a TODO to fix it one of these days.
nanotree · 68 points · Posted at 14:12:13 on April 26, 2018 · (Permalink)
Ah, nothing changes. Its almost comforting.
Theemuts · 36 points · Posted at 14:43:41 on April 26, 2018 · (Permalink)
//TODO: write witty comment
luckyvb · 17 points · Posted at 14:58:09 on April 26, 2018 · (Permalink)
//FIXME
Curtalius · 21 points · Posted at 15:42:05 on April 26, 2018 · (Permalink)
// I don't know what this does but everything explodes if I remove it.
ijustwannacode · 6 points · Posted at 15:21:19 on April 26, 2018 · (Permalink)
// This seems legit for now
arbitrarycivilian · 4 points · Posted at 15:41:47 on April 26, 2018 · (Permalink)
I'm broken on the inside
justjanne · 39 points · Posted at 15:07:38 on April 26, 2018 · (Permalink)
Or you build a prototype that ends up full of TODOs and FIXMEs, and then you build a second rewrite, piece by piece, carefully documenting and testing each part as it’s added (knowing the real requirements this time, constantly checking with the prototype), and you end up with a version where there are no bugs left, the code is clean and tested. And with more features, and it’s much more stable.
I’m almost done with a 2-year process of doing this right now, going from http://github.com/sandsmark/quasseldroid over https://github.com/justjanne/QuasselDroid-ng/tree/918688abd60c72efbe351e761892b65835fe4baf finally to https://github.com/justjanne/QuasselDroid-ng
At least for 20kLOC to 50kLOC, rewrites are useful and helpful. Maybe beyond the 50kLOC, 100kLOC or 1MLOC limit that changes. Also, during the rewrite you absolutely need to provide at least bug fixes for the old version.
regretdeletingthat · 13 points · Posted at 18:28:44 on April 26, 2018 · (Permalink)
Man, I wish I could do this at work. Instead, marketing has sold another year long project on a six month budget, and signed off another tragically bare “scope” without any developer input. Cue many months of trying to simultaneously build a system and decipher the actual requirements.
We have so many projects that are in upsetting states of disrepair and several with behaviour that is downright illegal once GDPR kicks in next month. But the boss knows the onus is on the client and not the contractor, and so nothing gets done unless someone else is footing the bill.
justjanne · 2 points · Posted at 18:37:22 on April 26, 2018 · (Permalink)
Yeah I can only do it because this project is more "fun" than work for me, and I don't have to pay my bills with it (although the Patreon and other donations certainly help)
iLikeStuff77 · 2 points · Posted at 22:56:31 on April 26, 2018 · (Permalink)
The concept that maintenance involves iterative refactors/rewrites to keep the code base sustainable is lost on too many developers.
It's also useful regardless of the size of the code, as long as all changes are thoroughly tested/documented.
paolog · 13 points · Posted at 16:01:34 on April 26, 2018 · (Permalink)
Psst, TDD. Not very useful if you are maintaining a heap of someone else's crap and you don't even know what the required behaviour is supposed to be, but you have to start somewhere with your testing.
pdp10 · 1 points · Posted at 23:45:54 on April 27, 2018 · (Permalink)
Awesome apocrypha. But it must have been a different program or a different year.
Full-screen editors weren't used until glass TTYs became cost-effective, right around 1974.
viwasn't released publicly until 1978, but it was developed at Berkeley and I'm not sure when it might have gotten into the AT&T codebase. But C wasn't even developed until 1972 or 1973, and all 1970 "Unix" source, such as it was, was in assembly.FlyingRhenquest · 1 points · Posted at 07:08:13 on April 28, 2018 · (Permalink)
197ish, I suppose. My memory's not quite photographic, and that was 199ish.
phySi0 · 1 points · Posted at 13:26:12 on May 10, 2018 · (Permalink)
A lot of things are just being taken as a given in this discussion. Who says you'll make all the same mistakes?
My axiom is that objectively bad code exists, not that a rewrite will always make the same mistakes. I think the first statement is what's self-evidently true, not the second, so I start from that. Sometimes, code is just bad for whatever reason, and a rewrite will not make the same mistakes.
FlyingRhenquest · 1 points · Posted at 22:54:25 on May 10, 2018 · (Permalink)
Yeah, it's more of an "on average" thing. You very frequently hear "This code sucks and has to be rewritten!" from programmers, especially junior ones. Junior ones who haven't seen the requirements. Assuming there are actually documented requirements. But most of the time when you hear that phrase, it's coming from someone who hasn't seen the requirements and is severely underestimating the time and scope required for a rewrite. Very frequently, they've also been on your team less than a month.
I'm not saying a rewrite is never justified, but in many of the cases you can just refactor toward higher quality and it'll be a lot safer for the customers who are using your code.
minionslave · 9 points · Posted at 14:23:02 on April 26, 2018 · (Permalink)
How to tell when it's plain bad, vs something that needs time to be understood?
Deathspiral222 · 17 points · Posted at 15:16:04 on April 26, 2018 · (Permalink)
"code smells" https://en.m.wikipedia.org/wiki/Code_smell
Anti-patterns https://sourcemaking.com/antipatterns
Also, using completely the wrong tool for the task, lack of unit tests for complex stuff etc.
HelperBot_ · 2 points · Posted at 15:16:08 on April 26, 2018 · (Permalink)
Non-Mobile link: https://en.wikipedia.org/wiki/Code_smell
HelperBot v1.1 /r/HelperBot_ I am a bot. Please message /u/swim1929 with any feedback and/or hate. Counter: 175227
beavertime · 1 points · Posted at 19:01:53 on April 26, 2018 · (Permalink)
Tools and techniques change, so it is possible that a codeset has "rusted" in the sense that it spent a lot of time and effort on something that a modern library or framework makes easy.
However regarding unit tests...I have noticed a bizarrely high correlation between terrible code and loads and loads of unit tests. Some of the best code I've come across has nary a test at all.
[deleted] · 4 points · Posted at 14:30:37 on April 26, 2018 · (Permalink)
That's a trick question! You can only tell after taking the time.
bythenumbers10 · 1 points · Posted at 16:46:45 on April 26, 2018 · (Permalink)
How easy is the code to get running? Seriously. If I can get it to say "hello world" in short order, or run a simple test case in idiot-proof fashion, then it may just take time to understand.
But if even following the "setup" or "introduction" instructions fails, the code is bad & needs serious work.
dablya · 1 points · Posted at 19:45:30 on April 26, 2018 · (Permalink)
If you have to ask...
Even if you don't, the code needs to be understood before it can be judged.
It rarely hurts to take a sympathetic approach to someone else's code.
pdp10 · 1 points · Posted at 00:08:51 on April 28, 2018 · (Permalink)
Indicators:
[deleted] · 23 points · Posted at 14:40:53 on April 26, 2018 · (Permalink)
And you think the new code is better? I guarantee you that there will come a future developer who makes the same statements about the new code. I realized this also that every code just becomes bad by lying around. So I asked around my fellow developers if they ever happened to see existing code which they considered good and didn't feel the urge to change anything. None every seen such a thing. So this is no way representative for anything, so tell me about your experience. Do you know such legacy code, which you would consider nice?
Edit: Oh now I opened the actual article. It's that one from APRIL 6, 2000. Yes 18 years ago the world was really a bit more messy than today.
[deleted] · 12 points · Posted at 14:28:02 on April 26, 2018 · (Permalink)
Very rarely. They did in fact have their reasons to make it like that, apparently the problem isn't as easy as it looks, and they had time constraints. Chances are you're being overoptimistic about your own future work as well.
I mean, maybe management has since decided that a much simpler approach is OK, or maybe you really are much better at programming than the people before you. But if not, it's just going to be a costly vanity exercise.
nikanjX · 22 points · Posted at 14:14:50 on April 26, 2018 · (Permalink)
You had 300 todos. You replaced them all with ”// TODO Implement entire app”.
Congratulations, you now have way less TODO entries.
lazystone · 6 points · Posted at 15:17:58 on April 26, 2018 · (Permalink)
This:
https://en.wikipedia.org/wiki/Lava_flow_(programming)
chcampb · 2 points · Posted at 14:43:13 on April 26, 2018 · (Permalink)
I think it's complicated with a lot of
In every single case, you should take that code, set it aside, and don't reinvent the wheel. If you are solving the same problem you will likely use some of that code again.
mrcrassic · 1 points · Posted at 16:03:01 on April 26, 2018 · (Permalink)
I don't give a shit about speed tape being in the code as long as it's readable, has high test coverage and is passing tests.
Unfortunately, speed tape to that extent usually means that one of those three things is being violated.
d36williams · 1 points · Posted at 17:07:07 on April 26, 2018 · (Permalink)
Or a software is fine for 2 or 3 years, but an alarming security update is needed, and no one knows the scripts and what will need to be updated. Or it was poorly built by the lowest bidder years ago for a paradigm the software doesn't even use anymore.
[deleted] · 1 points · Posted at 17:07:31 on April 26, 2018 · (Permalink)
[deleted]
CommonMisspellingBot · 1 points · Posted at 17:07:44 on April 26, 2018 · (Permalink)
Hey, threemanycats, just a quick heads-up:
seperate is actually spelled separate. You can remember it by -par- in the middle.
Have a nice day!
The parent commenter can reply with 'delete' to delete this comment.
maxdifficulty · 1 points · Posted at 18:24:04 on April 26, 2018 · (Permalink)
My personal favorite:
With no further details.
nickiter · 1 points · Posted at 18:29:11 on April 26, 2018 · (Permalink)
My first internship was fixing legacy code that was written with minimal comments, variable names like x, m, n, counter, etc, and was a seemingly random mix of object-oriented and linear approaches. It literally put me off being a real developer and put me on a path to my current technical-but-not-writing-software gig.
issafram · 1 points · Posted at 19:06:45 on April 26, 2018 · (Permalink)
i like the hard coded credentials that say //change password
theonejoliefolie · 1 points · Posted at 21:17:11 on April 26, 2018 · (Permalink)
Agreed. A big part of when to refactor is when the old code is inefficient, but works. If you're expecting to ramp up the sheer volume of the data you process, the old code might not be able to handle it in a reasonable fashion, hence a necessary rewrite.
13steinj · 1 points · Posted at 22:06:28 on April 26, 2018 · (Permalink)
There have been multiple cases where I started working on a company project and simply found that regardless of whether I thought it was "good" or "bad", it was severely unoptimized. Optimization isn't a necessity in most of these cases, but it's a nicety for both the end user who gets their info just slightly quicker and the server which gets to use far less resources and compute time over longer periods of time (on a one by one basis, sure, it's a millisecond, and negligible. But when considering thousands of calls, it matters quite a bit in regard to cost). If the code is bad, I refactor/rewrite it from the start. If it's decent (understandable by most of the team, doesn't cause any major issues), then I'll still refactor it, just opportunistically while adding / changing something at that level.
OneWingedShark · 1 points · Posted at 20:33:17 on April 27, 2018 · (Permalink)
Ever work on a codebase that began as a collection of unrelated "tools", then grew into a full blown application using at least three different UI frameworks?
DutchmanDavid · 1 points · Posted at 12:28:11 on July 2, 2018 · (Permalink)
Doing this right now for an internship D:
It's my first time with Angular (5 and .NET Core (2.1) though)
Diiix · -9 points · Posted at 14:18:51 on April 26, 2018 · (Permalink)
Le smart and good Redditor always does a better job than everyone else :^)
frog2112 · 133 points · Posted at 15:36:52 on April 26, 2018 · (Permalink)
As a programmer, I have about a 0% urge to “throw away” old code. However, I have a 100% urge to rewrite old code one function at a time.
[deleted] · 59 points · Posted at 16:06:23 on April 26, 2018 · (Permalink)
[deleted]
grauenwolf · 39 points · Posted at 18:59:53 on April 26, 2018 · (Permalink)
I've long stopped asking. If I'm tasked to add a feature to component A, step 1 is clean up, step 2 is bug fixes, then step 3 is actually adding the feature.
How can I do it any other way? How would I know the difference between a new bug and an old bug if I don't first fix all of the old bugs?
frog2112 · 14 points · Posted at 16:13:31 on April 26, 2018 · (Permalink)
In my case, I’m working with code that’s been around since the late 90’s. I’m just here like “This project is OBVIOUSLY gonna be around longer, just let me give some of it a makeover”, but of course that’s “not in the budget” or “not within the scope of the project”.
zynasis · 3 points · Posted at 21:06:17 on April 26, 2018 · (Permalink)
Or in government, up to 30 years.
jbuckets89 · 3 points · Posted at 23:13:52 on April 26, 2018 · (Permalink)
Yea, and that three years is usually rolling (after 2 years passes, it’s still about 3 years out)
NotACockroach · 2 points · Posted at 23:06:19 on April 26, 2018 · (Permalink)
Soon tm
pdp10 · 2 points · Posted at 00:12:05 on April 28, 2018 · (Permalink)
You misheard. The plan is to replace it in three years. Probably they'll start looking in four years. Around the sixth year, they'll give up and go with either SAP or Oracle. You won't believe it when you hear it, but you'll instantly realize then that the old code wasn't so bad, actually. If only it had just gotten a little bit of maintenance once in a while.
Plasticcaz · 2 points · Posted at 02:06:54 on April 28, 2018 · (Permalink)
I recently got hired to work on a project that's been "going to be replaced in three years" for a while now, so I'm told. We're still adding features.
Edit: spelling
[deleted] · 1 points · Posted at 22:51:49 on April 27, 2018 · (Permalink)
This is why I don't ask for permission. I just do it.
TheLastLivingBuffalo · 11 points · Posted at 17:29:31 on April 26, 2018 · (Permalink)
I try to do this as I'm working on bug fixes or features in a certain area. Refactor this class, rewrite that method. Then document, write tests, and move on. Doubles development time, but I think saves time and money in the future.
bmarkovic · 3 points · Posted at 10:09:31 on April 27, 2018 · (Permalink)
It's the right thing to do, and I'm being paid for it. So what, the features don't land as fast and I have less time for Reddit. After a while I've taught my non-tech managers or customers to adopt to the speed of actually doing it right and with refactoring included.
The techy ones with my current employers know it as well as I do.
bmarkovic · 2 points · Posted at 10:06:43 on April 27, 2018 · (Permalink)
This is exactly what Joel is suggesting, and he is/was right for large majority of software projects. Some codebases are really shitty beyond recourse, sometimes an old technology foundation of software must be abandoned because it's not possible/viable to continue using it but in most cases rewrites are just new people's arrogance and lack of experience.
The three software smells and the approaches to deal with them are also spot on.
Which is why the modular approaches like microservices are a good idea. You can evolve and rewrie incrementally.
There is a great story by Uncle Bob about an attempt in a company he worked for (or consultet for, can't remember exactly) to rewrite a core app, that took a decade while the original was still being developed and was thus a moving target. By the end of it the new code was as smelly as the old one.
PM__YOUR__GOOD_NEWS · 1 points · Posted at 13:54:21 on April 27, 2018 · (Permalink)
Man, when I learned to version virtually all my code my life got so much simpler.
None of this "Comment it out, might need it later", just hack it away and remember to commit early and often.
kcdragon · 145 points · Posted at 14:48:34 on April 26, 2018 · (Permalink)
I feel like Netscape and Borland are very different from the software most of us are working today. Netscape is a desktop application with a massive code base. I'm currently working on web services and front end apps on the order of 10k LOC. I feel like rewriting Netscape is a much bigger effort (and more likely to go wrong) than rewriting these front end apps and web services.
Also, FYI this article is almost 20 years old
GhostBond · 46 points · Posted at 23:34:43 on April 26, 2018 · (Permalink)
The more things change, the more they stay the same.
boojit · 3 points · Posted at 01:35:03 on April 27, 2018 · (Permalink)
I really think there has been a fundamental shift though that came well after this article was written. I think it can largely be summed up as a move from monolithic applications to services-based (or microservices if you must) architectures. Amazon really needed to move from a monolithic web app to one that was built on a constellation of independent services with well-defined interfaces, when they did it some 10+ years ago. The effort requires a complete rewrite of their entire business, but not doing so would have been a fatal error. I am sure there were people at the time that would have argued the rewrite was a bad idea. Those people were wrong.
tiajuanat · 2 points · Posted at 01:28:17 on April 27, 2018 · (Permalink)
Source, source never changes
ivix · -5 points · Posted at 18:32:27 on April 26, 2018 · (Permalink)
A 10k loc web service is tiny. I've designed and built services that are closer to 500k and over 10 years old. They are exactly the same situation as the projects in the article.
Scybur · 17 points · Posted at 19:09:14 on April 26, 2018 · (Permalink)
500k loc web service.....what an absolutely shit design.
ivix · 15 points · Posted at 20:15:50 on April 26, 2018 · (Permalink)
Yeah, let's rewrite it from scratch!
Ciaran54 · 15 points · Posted at 23:29:53 on April 26, 2018 · (Permalink)
Let's rewrite it in Scratch.
SArham · 6 points · Posted at 20:58:18 on April 26, 2018 · (Permalink)
Break it into multiple microservices and interface them together.
fragglerock · 3 points · Posted at 00:22:02 on April 27, 2018 · (Permalink)
Then you have all the lines of code AND an orchistration problem!
Jobs for life :-)
ivix · 2 points · Posted at 22:52:09 on April 26, 2018 · (Permalink)
It is several services but could be more.
UnShame · 5 points · Posted at 21:07:15 on April 26, 2018 · (Permalink)
Why? Maybe it's just a giant service like google docs or something.
gwern · 51 points · Posted at 15:15:08 on April 26, 2018 · (Permalink)
As Perlis put it all the way back in 1982:
IkonikK · 1 points · Posted at 20:26:27 on April 26, 2018 · (Permalink)
is that taking into account the negative effects of the incorrect program in the dev cycles?
khendron · 22 points · Posted at 15:24:26 on April 26, 2018 · (Permalink)
Any mature codebase will be full of non-obvious code that is there to support what I like to refer to as invisible requirements.
Invisible requirements are requirements that do not appear in any design doc or user documentation, but the existing codebase has been written to support them. They are often the result of architectural or design decisions made during the original development; modifications made to workaround bugs or performance issues; well-known application features being used by customers in unexpected ways. Invisible requirements often fly underneath the automated tests, and nobody knows that they are there except maybe the crotchety old developer sitting in the corner (if he or she even still works for the company).
Any existing codebase is chock full of invisible requirements. Starting again from scratch means going through the pain of discovering them all over again (or finding completely new ones). This is not necessarily a bad thing. Sometimes a codebase is so bad that you need to start from scratch. This is usually the case when you can't even make minor code changes without tripping over some invisible requirements.
Hawkknight88 · 2 points · Posted at 16:28:36 on May 3, 2018 · (Permalink)
An entirely valid point - and I expect to see comments explain WHY a certain piece of code exists, preferably with a link to the ticket!! It should also be in the commit message.
Without such comments the result will (IMO) inevitably be a shitty codebase with truly invisible requirements and no hope of understanding them all.
Lucent · 74 points · Posted at 16:49:09 on April 26, 2018 · (Permalink)
While he may have a point, he picked the absolute worst possible example in history to illustrate it. Netscape 4 was garbage. You couldn't even resize the window without a complete reload. Hundreds of glitches in rendering. Getting absolutely destroyed by IE in every way. They made the best decision of their lives ditching that buggy codebase and beginning what would become Firefox, a revolutionary browser at the time. I'm almost certain trying to build Firefox off Navigator 4 would've been an absolute failure and disaster.
singham · 27 points · Posted at 18:22:04 on April 26, 2018 · (Permalink)
The article is 20 years old. I think there should be a date tag just like hackernews has so people commenting has proper context.
nerfviking · 5 points · Posted at 00:01:56 on April 27, 2018 · (Permalink)
Holy shit, I remember this article. I thought it was stupid then, and two additional decades of programming experience has confirmed it.
Sometimes rewriting code is a bad idea. Sometimes a codebase is well and truly fucked, and it's holding you back. Most code is somewhere in the middle and needs to have time spent on it repaying technical debt. If you've got hacks upon hacks upon hacks, you're usually better off starting over.
grauenwolf · 9 points · Posted at 19:00:42 on April 26, 2018 · (Permalink)
Netscape 6 had the same problem.
vaderkvarn · 4 points · Posted at 18:03:06 on April 26, 2018 · (Permalink)
Wouldn't it still be better to release Netscape 5.0 just to stay in the game, and incorporating Gecko in 6.0 without the rush? A bit like how Servo has been a separate project for several years and is now being merged into Firefox.
pdp10 · 2 points · Posted at 00:18:22 on April 28, 2018 · (Permalink)
Netscape 4 was a rewrite from C to C++.
Jamie Zawinski tried to get the C codebase open-sourced in addition to the C++ one, but failed.
eddieSullivan · 16 points · Posted at 19:09:53 on April 26, 2018 · (Permalink)
As a freelancer who has taken on a lot of "fixer-upper" projects, I disagree a thousand percent. Most legacy code is garbage, and should be treated as such.
EastLondonCoder · 36 points · Posted at 15:50:53 on April 26, 2018 · (Permalink)
This article has an interesting way of ageing. When I read it the when it was first written I absolutely agreed with Joel, the rewritten version of netscape was absolutely atrocious.
However ten years later the decision to rewrite was completely vindicated with the success of firefox. Joels was then dead wrong. Mozilla would not have succeeded in making an IE killer tied to the very brittle code base of the original netscape browser.
Today the field is even more interesting, mozilla has a very interesting rewrite project with Servo. Now I think Joels main point stands, a lot of the instinct programmers have for wanting a rewrite is because it is much harder to read code than to write. As anecdata I do see a correlation with skill and how much maintaining a programmer has done
gmfawcett · 12 points · Posted at 22:27:19 on April 26, 2018 · (Permalink)
Servo/Quantum is actually a decent example of following Joel's advice. Mozilla didn't throw out the whole application at once, instead they are rewriting and replacing subsystems.
BenoitParis · 3 points · Posted at 13:15:10 on April 27, 2018 · (Permalink)
.. which in my opinion brings an additional benefit before you even start:
By carving out a scope to be rewritten, you are enforcing a modular structure of your codebase.
gmfawcett · 1 points · Posted at 13:45:19 on April 27, 2018 · (Permalink)
Sure, I agree.
In the case of Firefox, it already had a decent modular design, and so the approach is a natural fit. I'm not sure the same can be said about Netscape; I have never seen any of its code, but the general opinion is that it was quite a mess. So a "Netscape/Quantum" approach might have been doomed to fail.
Arch____Stanton · 1 points · Posted at 07:05:28 on April 27, 2018 · (Permalink)
They offered it up for free for the first time. That is what made it. Rewrite be damned.
If they had offered up Netscape for free, IE wouldn't have had such a huge market share to begin with.
pdp10 · 1 points · Posted at 00:24:02 on April 28, 2018 · (Permalink)
Netscape was available gratis, although I can't remember the license terms -- it might have technically been for personal use. I was using it from 0.99 to 4.78, if that was the last one. Netscape was trying to make money on the server side, but never really got traction except where operators needed SSL or needed a server-side GUI.
Microsoft licensed Mosaic from Spyglass for royalties, then gave it away for free as IE, producing zero royalty obligations. There was a lawsuit about that one.
Arch____Stanton · 1 points · Posted at 01:01:41 on April 29, 2018 · (Permalink)
I remember it being a paid app and I got the quote from Wikipedia.
So maybe you should go and edit Wikipedia because obviously they have it wrong;)
Actually you have it wrong, but not worth arguing.
Maybe you had some student deal or something of the sort, but most people definitely had to pay for it.
pdp10 · 1 points · Posted at 01:13:39 on April 29, 2018 · (Permalink)
It was downloadable from Netscape's FTP site. The downloadable version was 40-bit export-grade encryption, instead of domestic 56-bit. I don't know precisely what the license was; it may have been "personal use", "non-commercial", or possibly even "non-expiring trial" for all I remember.
Here's one mention from a point in time: 1998-01-23. I definitely ran earlier versions for free on SunOS, Alpha (OSF/1, Digital Unix), MacOS Classic, and IRIX, and possibly others. The IRIX version may have shipped from SGI.
shevegen · 249 points · Posted at 14:24:49 on April 26, 2018 · (Permalink)
No.
Very often the old code IS shit.
Reading may be harder than writing but that does not change whether the code in itself is bad.
I hate rewriting but very objectively the net result of the rewrite is often MUCH, much better than the prior version. This often happens because lateron it is more clear what the code should be doing; and whether it is doing it in a good way.
Sometimes a language design can also become better, and old expressions can be re-written in better ways too.
ProvokedGaming · 71 points · Posted at 15:19:44 on April 26, 2018 · (Permalink)
Very often the new code is also shit. Most large projects I've seen where the dev team decides to completely rewrite from scratch, they end up making a new giant codebase which is shit for completely different reasons, and it ends up taking way longer than anyone thought. Part of this also seems to stem from the fact that the rewrite team is rarely the exact same team that started the original project because too many years have gone by, so the rewrite is effectively the first time the current team has actually built the product. My own anecdotal evidence suggests rewriting pieces over time is almost always more successful than a full rewrite in one shot. Unless of course the codebase is fairly small.
LetsGoHawks · 21 points · Posted at 17:22:09 on April 26, 2018 · (Permalink)
Speaking as a end user for a moment...
How many times have we all seen a piece of software get replaced by a new, better piece of software. Often a completely new product by a different company. But it's not any better, it's just crappy in different ways. Every once in a while, it truly is better, but not very often.
rjsr03 · 1 points · Posted at 16:09:09 on April 27, 2018 · (Permalink)
This reminds me of that saying of "sometimes there's no right, just different flavours of wrong" or something along those lines.
dsk · 38 points · Posted at 15:44:28 on April 26, 2018 · (Permalink)
Bingo. Typical dev arrogance is usually on the display when they think they can do a better job than their peers just a few years ago.
Mine too. I maintain an app I build with a team ten years ago. There are plenty of things I would do differently I started all over again, but we have hundreds of customers and thousands of users - it works. If code area inevitably starts getting flakey (and it will happen), we re-design it and rewrite it.
Chrisdone2 · 8 points · Posted at 07:08:55 on April 27, 2018 · (Permalink)
I think you're confusing "I can rewrite this because we know what the system is supposed to be now" with "I can rewrite this because I'm a better programmer than the original authors".
dsk · 2 points · Posted at 09:11:05 on April 27, 2018 · (Permalink)
What's the difference?
pdp10 · 1 points · Posted at 02:12:22 on April 28, 2018 · (Permalink)
Different programmers.
scottious · 2 points · Posted at 11:46:20 on April 27, 2018 · (Permalink)
I believe that ALL code is shit, new and old. The minute any line of code is written, they become a partial liability.
I've been through many rewrites too. I know what you mean partially but I still think that rewrites have a net positive effect if they're done by people who really truly understand the problem, which usually means having struggled with the "old code" for a very long time.
[deleted] · 1 points · Posted at 15:25:15 on April 30, 2018 · (Permalink)
Are you me? I could have written this word for word
Merad · 48 points · Posted at 15:27:48 on April 26, 2018 · (Permalink)
It's very hard to overstate just how much shit code is out there, especially when you're talking about non-tech companies that don't put a high priority on software (aka most of the world). I'm not just talking about "I don't like this code," "this code isn't clean," or anything of the sort; I mean true steaming piles of shit. Here's a great example. At my last job our team inherited a 25+ year old application that was bad overall (to the point where we had to rewrite it), but one enhancement added in the late 2000s really stood out.
This feature involved connecting to a serial device using the .NET SerialPort class and reading measurements sent ~20 times per second. The data format was basically
STX1 NN 00\nwhere STX is the actual "start of text" character (0x02), NN is 1-6 decimal digits, and the spacing is variable but the length of each line is fixed (16 characters IIRC). In order to parse this, the original developers had come up with a 200+ LOC monstrosity that had three nested infinite loops interacting with 3-4 global variables, including a timer (???)... in addition to about 4 old commented out versions of the parsing code with the same basic layout. I never did manage to figure out how the hell that old code worked, but my replacement amounted to about 20 LOC total.CopperSauce · 19 points · Posted at 20:56:33 on April 26, 2018 · (Permalink)
Reminds me of the worst piece of code I have ever seen on finding a maximum. Back in college I took a difficult operating systems course in which you are partnered with somebody for the year. My partner happened to be pretty bad at coding.
One of the assignments, each of which takes about 100 hours over 2 weeks, was basically creating threading/processes, with a separate far easier segment for creating a scheduler. I told my partner I basically will do all of it, but I will pass to some function "grab next prioritized thread" for the scheduler and he just has to write the function on deciding which thread is next. He spent maybe 5 hours tops while I did the other 95% of the project, and I didn't bother reading what he had written for the code since it was working.
We got the project back docked for design decisions. I was baffled and spoke with my TA about it and asked why, and he pointed to the scheduler... Each thread was given a priority, and the highest priority thread was the one to be used next in the scheduler, so he had to write a function for "find the thread with highest priority".
The function he wrote... for finding a maximum...
Or basically, start at maximum possible number -- does a thread exist with this priority? No? Okay, repeat with maximum minus one. No thread? repeat... Until you find a thread... I couldn't believe what I was reading
Merad · 6 points · Posted at 21:41:27 on April 26, 2018 · (Permalink)
I don't know what you're complaining about, that algorithm always finds the highest priority thread.
/s (should probably be /cry)
tehftw · 1 points · Posted at 06:29:10 on April 28, 2018 · (Permalink)
I mean, umm, if the number of threads at some point is greater than UINT_MAX... What the fuck were they thinking?!
RagingAnemone · 9 points · Posted at 15:38:52 on April 26, 2018 · (Permalink)
Depends. Is old code shit because it’s bad? Or is old code shit because somebody else wrote it?
Many times this is used to replace code somebody else wrote and the new programmer doesn’t understand the new code and why it was designed that way. Then during the rewrite, you discover all the reasons why it was written this way. Reading code is its own skill and it’s under appreciated. It includes deciphering the original requires as implemented.
bythenumbers10 · 1 points · Posted at 17:04:02 on April 26, 2018 · (Permalink)
And you find out that it's been on life support for years (while every user loathes using the library) because the guy that wrote the core functionality as a young engineer is now management and protecting their own legacy, even though that little piece of code has since gone through puberty, gained oodles of stapled-on submodules like pimples, and attained young adulthood in a haze of alcohol-fuelled bug workarounds and getting high on outdated code quality and compatibility standards. Might be time to take the manager aside and break it to him gently that Jr. needs an intervention and rehab via a massive re-write, and when it comes out the other side as a brand-new version, that manager can still say, "I remember that software back when it was v0.10, because that's my baby." and take credit, even though now the code is a likable, well-adjusted, mature application instead of a buggy, immature ne'er-do-well.
Or insert whatever tale(s) of woe you like, but that is the nature of technical debt. Never paying it off makes the debt bigger over time. Now ain't that interesting?
Eep1337 · 48 points · Posted at 14:38:18 on April 26, 2018 · (Permalink)
for you, but what about for the customers?
Is a rewrite a success if you miss 50% of the features?
And I don't mean rewriting some small 20,000 line app....I mean rewriting a 1,000,000+ line enterprise app.
There is always a trade off.
grauenwolf · 46 points · Posted at 15:09:17 on April 26, 2018 · (Permalink)
Depends on whether or not those features were actually being used.
The hard work starts long before a single line of code is changed.
[deleted] · 11 points · Posted at 15:16:28 on April 26, 2018 · (Permalink)
[deleted]
grauenwolf · 14 points · Posted at 15:19:55 on April 26, 2018 · (Permalink)
That's why companies like mine exist. We'll interview your users, read all the regulations, document every screen, examine all of the code, etc.
It's mind-boggling expensive, but sometimes it is necessary.
flukus · 5 points · Posted at 22:38:29 on April 26, 2018 · (Permalink)
IME companies like that only interview management who have no idea what the employees are doing, so half the features get missed.
grauenwolf · 6 points · Posted at 22:45:51 on April 26, 2018 · (Permalink)
Yep, that's a frequent problem. And as you probably suspect, it often happens when management refuses to pay for user interviews.
What I don't know is if they refuse because of arrogance or a misplaced cost savings plan.
pdp10 · 2 points · Posted at 02:15:33 on April 28, 2018 · (Permalink)
Yes. Also, users might tell you something different than management did, and then there's a problem.
grauenwolf · 2 points · Posted at 04:10:34 on April 28, 2018 · (Permalink)
Only if we don't find out about it.
A lot of consulting work is finding these mis-matches between staff and management. Sure we write code, but that's really a small part of what we're about. (Which pains me to say because I don't want to be a consultant, I just want to crank out boring but useful software.)
dsk · 27 points · Posted at 15:38:42 on April 26, 2018 · (Permalink)
I think people clamoring for rewrites in this thread have tiny JS apps in mind. Yeah, I agree, in those cases - go nuts. Rewrite your Angular app in React because it's cool.
Rewriting a legacy enterprise application with hundreds of thousands or millions of lines of code will take years! In the meantime, there's a business that needs to run.
zellyman · 2 points · Posted at 16:31:30 on April 26, 2018 · (Permalink)
Eh, even this shouldn't scare you off. In a case like this you don't try a full rewrite at once, you tear off small pieces of functionality bit by bit.
dsk · 8 points · Posted at 16:40:06 on April 26, 2018 · (Permalink)
But nobody argues against that. That's the way you should do it. The entire debate rests on whether it is generally a good idea to do clean, total, group-up rewrites of large existing codebases.
skulgnome · 2 points · Posted at 12:27:43 on April 27, 2018 · (Permalink)
That's partial reworking, also known as maintenance, typically regarded the polar opposite of throwing it away and rewriting from scratch.
Eep1337 · 10 points · Posted at 15:44:44 on April 26, 2018 · (Permalink)
Yeah. I notice this sentiment a LOT with junior engineers coming into my company (we do legacy enterprise, go figure)
It is a delicate thing to explain. To be a great engineer in a shop like this you have to be equal parts engineer and businessman.
These days I try to incorporate a bit more communication and general business knowledge in my training rather than just "go here to debug this"
I want to prepare these kids for whatever the world might throw at them, and from what I've seen so far, understanding the business (even at a shallow level) and being an effective communicator will get you that raise and that recognition. Those skills will translate anywhere.
ckwop · 6 points · Posted at 21:09:21 on April 26, 2018 · (Permalink)
The way I explain this to my staff is to just look through the history of the industry at even a superficial level and you'll know that large software projects are incredibly risky.
Many are never delivered. Most are late. Most don't finish with the intended scope.
If you re-write your main application, which has had year after year of hammering on it by developers it will be a large project and possibly the largest one ever undertaken in your business.
Large projects tend to fail more often than smaller ones. There's a reason for that. When we double scope, we do not double effort. Effort does not scale linearly, According to COCOMO, it scales between n1.05 and n1.2
These rewrites are usually far, far larger than any project previously attempted. It will take far more effort than anyone predicts and because it's so expensive it will probably be less capable than the system it replaces.
zuchuss · -3 points · Posted at 23:05:52 on April 26, 2018 · (Permalink)
Mhm interesting. I would just add though that unless your degree is ABET accredited then you need to put engineer in quotes.
For example, I'm sure you work with a lot of software "engineers."
[deleted] · 1 points · Posted at 23:41:49 on April 26, 2018 · (Permalink)
[deleted]
zuchuss · -2 points · Posted at 00:02:36 on April 27, 2018 · (Permalink)
Well you guys used to call yourselves programmers but I guess that title just didn't carry enough weight anymore and so it went to software developer and then of course the infamous "software engineer."
Don't get me wrong, there are truly real software "engineers" out there. People that work at a low level with a fundamental understanding of what goes into it and design things like operating systems, engineering software, etc.
Most however will never leave the safe space of Visual Studio.
GimmickNG · 2 points · Posted at 04:05:29 on April 27, 2018 · (Permalink)
Just because you don't "leave the safe space of visual studio" doesn't mean you aren't a software engineer. I'm no software engineer but I'm pretty sure that writing a million lines or more of code requires some form of engineering, at least.
zuchuss · -3 points · Posted at 05:03:46 on April 27, 2018 · (Permalink)
import numpy as np
certification = ["""print("im an engineer")""" for i in range(999999+1)]
np.save("muhengineeringcert", certification)
look boys im an engineer now
Weepitywop · 1 points · Posted at 13:07:48 on April 27, 2018 · (Permalink)
Which part of "a million lines or more" did you miss?
zuchuss · 1 points · Posted at 14:50:04 on April 27, 2018 · (Permalink)
That produces a million lines of code written to a file (space delimited). Clearly you don't understand even the most basic code but you felt qualified enough to drop your 2 cents. Found the IT guy.
Weepitywop · 1 points · Posted at 16:58:57 on April 27, 2018 · (Permalink)
He did specify writing, I'm not sure programmatically generating the code really applies.
Even if I was an IT guy, I'd be glad I'm not insecure enough to have to validate myself by berating others on the internet :)
zuchuss · 0 points · Posted at 20:00:54 on April 27, 2018 · (Permalink)
That is writing the code, and the purpose of my earlier post is to simply expose the fallacy in your logic. Further arguing semantics makes you look quite the dunce.
GimmickNG · 1 points · Posted at 04:00:11 on April 28, 2018 · (Permalink)
using a strawman fallacy to expose a supposed fallacy? nice logic man, i want whatever it is you're smoking. go take a look at the linux source code, or any large system and tell me you don't need any software engineering skills for that.
zuchuss · 1 points · Posted at 05:35:17 on April 28, 2018 · (Permalink)
Not a strawman at all. Glad you agree on the part where the fallacy was exposed though.
GimmickNG · 1 points · Posted at 06:40:48 on April 29, 2018 · (Permalink)
i'm not sure what you're getting at. you wrote a program to write a program with a million LOC. That means you just wrote a single 3 line program, and the program wrote the code. Ignoring the fact that you can compress that code into a single for loop and thus invalidating your entire argument, you seem to be missing the point. whether it's because you're a troll or you're simply thick, i don't know.
zuchuss · 1 points · Posted at 06:44:47 on April 29, 2018 · (Permalink)
Actually my program was 3 lines. You have no clue at all what you're saying. Come back when you can count to 3 correctly.
GimmickNG · 1 points · Posted at 08:04:10 on April 29, 2018 · (Permalink)
ah, so you admit it's not a million lines! congrats on being wrong. you had no clue, have no clue, and will never have any clue of whatever you're saying because you're a fucking moron. I weep for the education system that failed you.
zuchuss · 1 points · Posted at 08:45:09 on April 29, 2018 · (Permalink)
Dumb.
GimmickNG · 1 points · Posted at 12:48:00 on April 29, 2018 · (Permalink)
I see you're finally becoming self aware.
zuchuss · 1 points · Posted at 05:18:00 on April 30, 2018 · (Permalink)
But you can't see that 1 + 1 + 1 ≠ 5.
GimmickNG · 1 points · Posted at 09:43:45 on April 30, 2018 · (Permalink)
nice nitpicking; i've fixed my post but your logic's still fucked up at the end of the day
zuchuss · 1 points · Posted at 09:50:25 on April 30, 2018 · (Permalink)
Lol you went back to ninja edit.. I mean "fix"... a post so you don't look like such an idiot... When we're the only ones who will probably ever see it. Dunno if I should laugh or cry because buddy, that's pathetic. This has ran its course.
GimmickNG · 1 points · Posted at 17:49:12 on April 30, 2018 · (Permalink)
ninja? boi u must be blind if you think that's a ninja edit. i literally told you i fixed it just now and you think that's a ninja edit? get some glasses
bythenumbers10 · 6 points · Posted at 16:53:02 on April 26, 2018 · (Permalink)
what happens if that massive codebase still needs a re-write, and its shitty architecture means it can't be modularized and re-written in pieces?
It's cute that companies pretend their 20+ year old code is "time tested" and "stable", that taking months or years to make changes is the "cost of doing business", and browbeat new hires trained in more modern, better tech into accepting that change is impossible and there's no fixing the codebase will allow that company to survive. Stagnation is only going to ask for trouble. Better to rewrite now and be able to run both systems against each other, than have to fire up an antique when the old system and its language is no longer supported by newer hardware.
dsk · 14 points · Posted at 17:12:34 on April 26, 2018 · (Permalink)
Then you do a rewrite. The point is that a rewrite is something that is done as an absolute last resort - when you've dismissed all other alternatives.
I don't know what to say about that other than the fact it is an incredibly shallow and naive perspective. It's easy to make proclamations when you aren't actually running a business and needing to actually bring in revenue to pay your expenses.
bythenumbers10 · 3 points · Posted at 17:54:35 on April 26, 2018 · (Permalink)
Watched it, experienced it, my man. Perhaps it's not a practical point of view, but waste is waste. In this case, time, money, and effort in maintaining a stack that acted like the Leaning Tower of Pisa, and it's still a matter of time before the whole thing collapses and then no business is getting done.
But by all means, run up that technical debt and move on to greener pastures before you're stuck footing the bill on a long-overdue rewrite.
grauenwolf · 6 points · Posted at 18:56:43 on April 26, 2018 · (Permalink)
There's no such thing. Refactoring the code without changing functionality is always an option. The first half of my career was solely dedicated to taking bug balls of mud and iteratively cleaning them to the point where you could make decisions about replacing individual components.
salbris · 2 points · Posted at 21:34:13 on April 26, 2018 · (Permalink)
One thing that confuses me is how a single package with millions of lines even exists. So many platforms have ways to nicely divide code so I would hope developers would use that. If they didn't then it probably means code quality is low as well. Maybe don't do a rewrite but maybe replace each feature one at a time. Or identify a smaller section of the product that can be rewritten.
burnmp3s · 3 points · Posted at 15:08:00 on April 26, 2018 · (Permalink)
Sometimes it's hard to separate features with bloat in general. The example in the article is Netscape, and in terms of web browsers I switched to Chrome because it was lighter and less bloated compared to Firefox which did have more features. With a redesign higher quality can trump quantity.
justAPhoneUsername · 2 points · Posted at 17:24:58 on April 26, 2018 · (Permalink)
If you are missing intended features then it isn't a rewrite.
Eep1337 · 1 points · Posted at 18:30:08 on April 26, 2018 · (Permalink)
you rarely miss the intended features.
It's all the OTHER features you might miss. Accidental ones (the old "bug is a feature"), or features hidden in messy code.
At the end of the day, in a large enterprise application, having 100% feature documentation is not easy. When you rewrite, you risk messing with the end users work flow, even if you "fix" things that should have never happened in the first place.
Relevant XKCD
earthboundkid · 2 points · Posted at 17:25:39 on April 26, 2018 · (Permalink)
Google Docs has less than half of the features of Word, and Spotify has less than half the features of iTunes.
You rewrite when the business environment changes so that the features you thought were vital no longer are.
[deleted] · 2 points · Posted at 17:34:50 on April 26, 2018 · (Permalink)
A rewrite shouldn’t break anything. If you’re removing features with your rewrite, you’re doing it wrong (where do you work that this is ok?). All tests (automated or manual) should still pass.
The reason it doesn’t happen is because PMs don’t want to assign work that isn’t needed. If it ain’t broke...
Now, if people are having problems because of some code that’s a different issue.
therealjerseytom · 6 points · Posted at 15:02:12 on April 26, 2018 · (Permalink)
Completely agree.
Granted, my experience is limited to:
I feel like inevitably, the requirements or use of a tool or application will outgrow its initial scope. It's a question of when, or how well the initial architecture was designed for extension and maintenance.
Eventually, the cost of a ground-up rewrite outweighs the misery of an increasingly convoluted, difficult-to-maintain/develop codebase. I've only gone and done this a couple times, but it is so worth it in the long run. Better foundation that's 10x faster to develop with, easier for new people to jump in and contribute, etc etc.
mykr0pht · 7 points · Posted at 15:27:21 on April 26, 2018 · (Permalink)
This. This is 1 of 2 essential reasons why re-writes are tempting in any codebase that lives long enough. (I still don't advise it though.)
The trick here is that how "well" you designed the system for extension is based on how well you can predict future requirements changes. And predicting the future is notoriously hard. Example: following open/closed principle, etc. everywhere in a system that doesn't end up changing results in a codebase that is unnecessarily hard to read.
therealjerseytom · 2 points · Posted at 16:33:19 on April 26, 2018 · (Permalink)
Yup. For sure. Totally agree. "Getting it right" the first time around is difficult if not impossible. Compounded of course if there's a pressing time constraint and there's the desire/need to just get "something" together without really sitting down and thinking it out up front :)
TheCoelacanth · 3 points · Posted at 16:52:59 on April 26, 2018 · (Permalink)
10k lines is a micro-project. I would have no qualms about rewriting something that size. Even 100k lines is not too bad. When you get to the millions or tens of millions of lines, attempting a complete rewrite is doomed to failure. You are throwing away a huge amount of hard-earned domain knowledge by doing that. An incremental rewrite is the only way you can possibly succeed.
nickiter · 2 points · Posted at 18:34:45 on April 26, 2018 · (Permalink)
It's also important to remember that teams of devs get better over time - the code your buddy wrote two years ago may be vastly worse than the code you're writing now, but you might have done just as badly.
skulgnome · 1 points · Posted at 12:25:48 on April 27, 2018 · (Permalink)
This is what it sounds like to not yet have learned from one's mistakes: rewriting seeming always like a good idea. Even worse if that turns out to be true!
LukeLC · 11 points · Posted at 18:31:05 on April 26, 2018 · (Permalink)
As someone who threw out an entire codebase and spent the last two years rewriting it: no, I was not wrong. There's good (bad?) reasons it was difficult to read before: it was a mess. The new codebase is so well organized I can put it down for long stretches and get reacquainted with it easily.
The key here is whether you're scrapping an idea or just your execution of it. In my experience, my original ideas are often sound, and when I later ask why I thought of something so ridiculous, it usually turns out there's very good reasons for it. But execution can always be improved, and sometimes that requires low-level rewrites. Everything else is just iteration.
generally-speaking · 10 points · Posted at 14:43:32 on April 26, 2018 · (Permalink)
I mean, where I work the control software we use has been in continous development since the early 90s. Which makes changes which would take 5 minutes on new code take 4 hours instead.
There comes a point when the old code should be thrown out.
colly_wolly · 9 points · Posted at 17:23:09 on April 26, 2018 · (Permalink)
If its shit code of course it will be harder to read than write.
The idea of the rewrite is to make it easier to comprehend.
blackholesinthesky · 31 points · Posted at 16:47:36 on April 26, 2018 · (Permalink)
Back in 2013 I pushed my team to rewrite our codebase in RoR. Originally it was a 600k+ line PHP and JS app.
It took us roughly 3 months to get stable.
We learned from our mistakes. I 100% stand by my decision. The increase in productivity was invaluable. The code base is now less than 30k lines. Don't haphazardly rewrite your entire codebase, but don't take this article too seriously either.
Edit: I realized I wasn't counting the templates in the RoR app while the templates in the PHP app were all included in my initial count. And in an effort to be fair, a more accurate total for the RoR app actually stands at 41k lines. While going back to investigate I also found that the PHP app had a 25 line license in almost every file, amounting to roughly 86k lines of license.
rageingnonsense · 5 points · Posted at 19:43:12 on April 26, 2018 · (Permalink)
Its all subjective. There ARE codebases that have so much technical debt that you can't possibly fix it all without it being a re-write anyways. Then there are cases where a re-write is temping because things are not perfect, but in reality the code base is good enough to get the task done.
For the cases where a codebase really has to be re-written, I find it is almost always because one or both of these reasons:
The second item is really important. Project leads a lot of times think they have to review code, but their own code does not need review. this is false. Noone is immune to making mistakes, and I firmly believe that every piece of code in a system should be reviewed by at least another person regardless of the seniority of the person writing it.
Daakuryu · 37 points · Posted at 16:34:43 on April 26, 2018 · (Permalink)
Except that's it's not AND it's not the reason most people want to throw out old code.
There are changes in technology, there's bad design and bad code out there and constantly applying bandaids instead of biting the bullet and starting fresh is a bad way of looking at things. I'm not saying throw out the code every time but there needs to be a line drawn at some point.
Case in point some of our in house software is in VB6; It uses controls that have no 64 bit version ocx because whoever made the controls stopped existing before 64 bit os and I'm not even sure we could get them working registered on windows 7 32 bit for that matter. This means we have to have a windows XP VM in our pool in order to make bug fixes or update features and hope to god nothing happens to corrupt that box and its backups.
It also means I can't install VB6 into a more recent version of windows to run debug in an environment that matches what one of my users has. Instead when I want to debug something I'm not experiencing on DEV I have to add a ton of Msgboxes that yell various profanities where I THINK the crash might be and see which profanity doesn't pop up. Had an instance where the user changed his region settings to french, and it Borked a CDATE() somewhere because it didn't know how to deal with the french version of the Month.
The programs talk to a set of access databases and has some of the most convoluted code I've ever seen. I hate that code with a passion, doesn't mean I can't read it, it's just retarded.
For instance whoever coded this originally made a Replace function that overwrites the built in Replace function with a significantly worse one that is prone to infinite loops, because why the fuck not?
Or how about the fact that every table is loaded into a "temporary" table before being read.
seriously...
Everywhere in the code there is a call to a function that drops tblTemp followed by a select * into tblTemp from whatever table they need at the time no joins or anything fancy like that and THEN the code does a select * from tbltemp where blahblahblabedyblah.
This software runs at over 60 locations across the country, I have to interrupt these people's workdays for 20-30 minutes to run fucking compact and repairs in access at 99.9% of these locations on a weekly basis because they run the risk of hitting the 2 gig database limit.
Not to mention every SQL command you have to write has to take into consideration the fact access is a "special needs" child and doesn't like to follow normal conventions. It's the Internet Explorer of databases.
There is stuff in there that has 100's of lines of buggy code doing things which I could do in 20.
Have I mentioned it's VB6 code yet? Yes I have. Know what that means? No Try/Catch. Error handling/logging is shoddy at best and non existent in most cases.
Here's the thing, I can read old code fine... the problem is that it reads like the fucking Twilight Series...
rageingnonsense · 3 points · Posted at 19:21:48 on April 26, 2018 · (Permalink)
I understand your pain with Access. I help maintain an EOL software originally written in Access, that is being ported bit by bit into another tech stack. The things you have to do in Access to get it to behave is nuts.
A the very least, the majority of the tables are linked; internal tables are only used as temp tables. Even so though, it does not scale. Its something that is great for a small business with like 20 employees max, but if you ever want to grow, you will need a new tech stack.
"Of course " & _
"I would do " & _
"Anything " & _
"to never have to do this shit ever again"
Daakuryu · 3 points · Posted at 19:48:23 on April 26, 2018 · (Permalink)
Yep, I just did a full deployment of SQL Server 2014 (2016 is not compatible with windows 7) to all my users over the past month.
Took about a week to download, install and configure SQL Itself on all the computers and I was doing 4-5 machines at a time (Thank you Logmein.), had to fight a couple users because they kept stopping the download.
Then three weeks of setting up individual copies of the new SQL database, dropping in a linked tables version of the old db's, creating odbc connections and making sure everything loads.
Probably would have gone a bit faster but;
I'm the IT Swiss Army Knife (Net OPs, Tech Support, Coder, Office Support, New System builder, pretty sure I have a toast function you can access with a nipple or something.) so I can be stopped by random crap at any time.
Had to stop deployment occasionally to do some emergency code changes because certain things we do in the old apps and in the newer .Net apps we've added over time don't behave well with linked tables. Like Sub queries, anything with a sub query will time out if you go through a linked table. Linked tables also don't like it if you try to do a read of records that are not committed.
At least for the .Net stuff I was able to just change connection strings, which provider to use and then de-accessify the SQL queries. The VB6 stuff required either a full workaround or getting rid of transaction/commit/rollback functionality.
The trick now is to finally get the boss to OK a rebuild but convincing him to keep the new versions as Forms Apps, not Web Apps which he seems to have a huge boner for right now... because that is a whole other nightmare and I will not do code fixes for web apps.
I am way underpaid for the amount of bullshit I have to deal with '-_- but I'm pretty sure no other company would tolerate my issues at this point.
rageingnonsense · 3 points · Posted at 20:02:12 on April 26, 2018 · (Permalink)
Why would you install SQL server on every machine? The idea is to have a centralized server that everyone connects to via an ODBC connection. How would you keep the data synchronized otherwise? Maybe I misunderstood you.
You absolutely can use sub-queries in linked tables, you just may need to bypass Jet if you want to get performance. You can do this by bypassing ODBC altogether within the VBA for certain queries, and running native T-SQL instead. However, subqueries can be slow in general. You can get a similar effect using CROSS APPLY and OUTER APPLY instead, and it generates a much better execution plan. For example:
This is faster than using an equivalent subquery (of course there are other ways to write this trivial example, but just trying to demonstrate the syntax).
In fact, I suggest bypassing ODBC altogether unless you need to also interface with local tables within an Access DB, or you need to use it as a form recordsource.
Daakuryu · 3 points · Posted at 21:01:47 on April 26, 2018 · (Permalink)
Because the machines are located across the country and they are self contained entities(Independently operated stores to be precise, we just provide the branding, the tools they need to do the job, the access to our supplier base and the support.) They need to be able to do things regardless of whether or not their internet is down, our internet is down or the universe explodes.
There is no point for instance in forcing the user to go out to the internet, to OUR servers and back to.
Lookup or modify the price of an item on the shelf then print a new shelf label.(Which will also automagically update the cash registers.)
Do the receiving of a pallet that just got dropped off.
Make an order to restock the shelves.
Check if the item in the empty peg/shelf is worth re-ordering of if they should just try a new thing.
Bought bunch of stuff from an unauthorized vendor? Authorized Vendor sent a substitute instead of the item you ordered and it's not in the system so it doesn't scan? Don't need to call ME or the Moichansing department, takes literally a minute to add it in.
All stuff they can do quickly and efficiently at any time with their handheld scanners (which is running good, clean .net code.) because they are working locally.
This is one of the main reasons I am against going Web App as well. Centralized over the web gives two hard failure points for EVERYTHING(Net is down at A or B) and a soft failure point as well(Net is slow somewhere down the pipe).
Net goes down? Only thing they can't do is hit the send button on new Orders to Suppliers but they can make the Orders just fine because everything except that Send button is done within the confines of the store itself.
Now Centralize all that or build a web app. Net goes down? Huge chunk of the stores operations just went belly up. Net's slow? Every single thing they want to do now takes that much extra time.
As far a sync goes we already had a set of Polling software's (one up, one down) that would sync our data with theirs on a regular basis, that is the .Net software I changed to use Native SQL connection.
Never said you can't, I said it doesn't behave well with it which is why where I could I nixed the ODBC/Linked Tables and wen't native SQL instead.
I still have some work cut out for me but by the time I am done the only thing that will use the old databases will be the two VB6 programs.
rageingnonsense · 2 points · Posted at 00:06:14 on April 27, 2018 · (Permalink)
Ahh I get it, its an end user product. I thought it was a single business with a lot of locations. I'm double surprised that you are stuck with VB then.
I agree with you that a web app is a bad idea; it just opens up security issues. Remind your boss that the Equifax hack happened through a web based API.
ericgj · 1 points · Posted at 18:02:45 on April 26, 2018 · (Permalink)
Oh man I thought I had it bad maintaining old VBA/Access applications. I started to write "have you tried..," and "what about...?" but it sounds like you crossed that line of "rewrite or be tortured" about a decade ago :) My condolences.... hope you find a way out!
overwhelmf · 1 points · Posted at 15:33:45 on April 28, 2018 · (Permalink)
ROTFL I feel so guilty from finding this hilarious but I do! Also, "2 gig database limit," that can't be normal? I apologize in advance I'm super new to programming.
Daakuryu · 3 points · Posted at 17:08:25 on April 28, 2018 · (Permalink)
Nope, you hit 2 gigs and everything stops working until you either compact the database (if you can) or split it.
Most of the time a compact is fine because the 2gb is mostly bloat due to the fact access doesn't actually clean up after itself Delete commands, drop commands, indexing, basically everything you throw at it gets stored inside the db in a set of hidden tables and it's only removed when you compact.
The reasoning behind it is that it was built as a 32bit application for 32 bit OS which had a 2gb ram limit on applications
as for the "special needs" comment
True; Rest of the world: 1 or 'True', Microsoft Access: -1 or True
Dates Rest of the world: 'A Date', Microsoft Access: #A Date#
Getting a date Rest of the world: GetDate(), Microsoft Access: Sends a Dick Pic... err I mean Now()
Where Clause Rest of the world: Where A = B And (C <> D or C < E), Microsoft Access: Where (((((((((((((A =B))()() and )))((C <> D) or ¿ C < E)))))))&$@ I may be slightly exaggerating the level of retardation but go play with the query builder in access on day and see how many () it adds to fairly straightforward where clauses.
overwhelmf · 1 points · Posted at 19:25:16 on April 30, 2018 · (Permalink)
the amount of parenthesis in Lisp drives me crazy
Daakuryu · 2 points · Posted at 14:44:15 on May 1, 2018 · (Permalink)
I mean you're talking about a programming language named around a speech impediment... Makes sense to me that it would be annoying to put out.
wwqlcw · 6 points · Posted at 15:17:36 on April 26, 2018 · (Permalink)
I think it would be very interesting to see how developers' attitudes about this "rewrite vs. fix it" issue corresponded with years of experience.
I'd guess that new developers would lean toward "fix it," developers with a few years of experience would turn toward "rewrite." And the grizzled vets would be back at "fix it."
Piecemeal refactoring isn't something most developers enjoy, but in contrast to a total rewrite, it can produce positive, tangible results very quickly. It can be fun. It is also, from a business standpoint, safe and cheap.
Fast, safe, cheap: choose any three. How often do you get an opportunity like that in engineering?
Something Spolsky doesn't mention here, but something I've noticed in my own projects: What you recognize as "cruft" in old code that someone else wrote often turns out to be, on much closer examination, "features." It's not until you examine it in the kind of detail required for a rewrite that you realize all the subtleties of the way Feature A and Feature B interact with each other. Your rewrite might be slightly cleaner than the original, but it's not going to be the sleek glistening monument to your own genius and discipline you imagined when you started, because the interaction between A and B just turns out to be complicated. Not complicated as a programming exercise, but actually complicated in the real world.
[deleted] · 6 points · Posted at 15:58:41 on April 26, 2018 · (Permalink)
[deleted]
chompsky · 1 points · Posted at 16:17:23 on April 26, 2018 · (Permalink)
My current project is the only time I've ever actually rewritten a codebase, and the only reason I even considered it was because the application is small and it was actively corrupting and exposing data. It's the only web application I've come across that would merge and corrupt data if two people interacted with it at the same time.
thegeicogecko · 6 points · Posted at 17:04:14 on April 26, 2018 · (Permalink)
The reason I want to throw away old code is because when you first write a program, you aren't really sure what the best way to do things are. You might not even be quite sure what you want to do. Once you write the program, you have a much better idea of these things, and could rewrite the program in a much cleaner way.
Of course, your manager doesn't want to allocate time for that, because the first version works, doesn't it? So then a year goes by, and someone looks at your code, and wonders to themselves: 'what the fuck is this?'
colly_wolly · 1 points · Posted at 17:21:50 on April 26, 2018 · (Permalink)
Its always worth doing a half decent job of a proof of concept / prototype, as the chances are it will end up in production.
thegeicogecko · 2 points · Posted at 03:14:38 on April 27, 2018 · (Permalink)
You do as good of a job as you can with the time you're allocated. Sometimes it ends up shitty because you barely get the thing working in time.
Zarutian · 1 points · Posted at 20:37:14 on April 26, 2018 · (Permalink)
Have always looked at this kind of refactoring as a kind of machine mantenance.
There is gradient of these none, very minimal, minimal, okayish, slight improvements done too, and quite a few improvements mantenance.
Example of very minimal is perhaps just rubbing the thing down with a cloth. Minimal making sure that it is lubricated, tensioned and such. Okayish is then on the order of regularly cleaning it out, inspecting and replacing worn out parts and such. Then there are improvements like replacing a faulty sensor type for a better one, adding belt tensioners springs or such. And at last a few examples of quite a few improvements is adding sensors and control board for something that had to be checked manually otherwise. That sort of thing.
Most managers do not see the value of going beyond minimal or okayish mantenance though.
[deleted] · 11 points · Posted at 15:29:50 on April 26, 2018 · (Permalink)
Yeah I feel like the general consensus here is that the title/article is ridiculous. You know a good code base when you read through it and similarly, you know a shit code base. The amount of technical debt that gets built up over months/years of maintaining bad code is incredible. And the amount of time wasted is too. I don’t know why programming is viewed as different from other fields; you wouldn’t write a report and submit your first draft. You write some ideas that get your point across, but it’s shit and not structured well, so you keep small parts and rewrite most of it. The only difference is that writing a code base takes longer and passes through different hands. But the goal should always be to write the best piece possible and improve where things can be improved, not persist trash
sapientias · 5 points · Posted at 04:51:37 on April 27, 2018 · (Permalink)
As someone who is not a programmer, I can’t imagine how frustrating (and rewarding) some of that coding may be. Props to all of you, and I appreciate what you all do for the world.
loup-vaillant · 29 points · Posted at 14:10:31 on April 26, 2018 · (Permalink)
Those aren't bug fixes. Those are workarounds. The system underneath the program has bugs, is unreliable, or has various quirks that make those workarounds necessary. But the bug certainly isn't fixed, merely sidestepped.
Oh I understand the incentives: if your program crashes because of a bug in the Windows runtime, it is your fault, not Microsoft's. If your game has glitches whenever it hits some bug in the graphics card driver, it is your fault, not Nvidia's. When customer see your program not working because their setup is broken, it is your fault for not foreseeing that, not theirs for not investigating. Basically any flaw that your program reveals is your fault, because the final judge is sales figures.
From this perspective, I'd understand why Joel would talk about bug fixes. But let's be honest, a "bug fix" that actually gets around a limitation of the underlying system is not a bug fix. It's an unnecessary kludge that could have been avoided if the system makers (in this case, mostly Microsoft), did their job and delivered something that works.
kevingranade · 21 points · Posted at 15:22:00 on April 26, 2018 · (Permalink)
Redefining words is fun.
Those aren't bugs in the underlying system, they're how the interface works. If a MS API or POSIX or JavaScript or c++ or Haskel require you to use magic incantations you don't like the sound of to make them do what you want, it's frustrating, but it's not a bug, it's dealing with reality.
1-800-BICYCLE · 6 points · Posted at 15:45:03 on April 26, 2018 · (Permalink)
Buggy interfaces are real.
skulgnome · 1 points · Posted at 12:22:10 on April 27, 2018 · (Permalink)
As are bug-compatible implementations.
loup-vaillant · -2 points · Posted at 17:47:40 on April 26, 2018 · (Permalink)
That reality you speak of has been forged by flawed fellow humans. Sometimes they make crappy interfaces. Sometimes the crap is undocumented. And more often than we care to admit, there's a genuine bug in the system we are relying on.
Getting around crappy interfaces should not be necessary. Dodging undocumented edge cases should not be needed. Getting around system bugs should not be the responsibility of the application developer.
There's the reality we can't change, and there's the reality we can rebel against with torches and pitchforks. Crappy interfaces, operating system bugs, CPU bugs, driver bugs… are the latter.
kevingranade · 2 points · Posted at 22:40:23 on April 26, 2018 · (Permalink)
I agree with you, except to the degree that you characterize code written to conform to the underlying system as a bug.
Is code that abstracts away the difference between the windows file API and the POSIX file API a bug? Certainly not. Am I going to get rid of it as part of my migration to c++17? Definitely.
You can deprecate system idiosyncrasies and bugs without characterizing the code that conforms to them as being bugs, and pertinently for the discussion at hand, if you remove those workarounds in a rewrite, you broke the code.
loup-vaillant · 1 points · Posted at 23:00:37 on April 26, 2018 · (Permalink)
Whoa, slow down there. I never said the workarounds were bugs themselves. I am merely infuriated by their necessity.
[deleted] · 7 points · Posted at 17:16:00 on April 26, 2018 · (Permalink)
[deleted]
[deleted] · 3 points · Posted at 23:05:24 on April 26, 2018 · (Permalink)
We use .toUpper() everywhere, wanna fight over whose shitty solution for a stupid problem is better?
rhino-x · 1 points · Posted at 03:33:31 on April 27, 2018 · (Permalink)
.ToUpperInvariant() is best toupper
dsk · 8 points · Posted at 15:46:45 on April 26, 2018 · (Permalink)
Also known as 'REALITY'.
loup-vaillant · 1 points · Posted at 17:49:34 on April 26, 2018 · (Permalink)
See my response here.
[deleted] · 15 points · Posted at 16:53:45 on April 26, 2018 · (Permalink)
Nope, that old code is actually a mess.
RumbuncTheRadiant · 1 points · Posted at 21:10:00 on April 26, 2018 · (Permalink)
Yup. Clean Slate, Solid Foundations, this time you'll do it Right!
blazingkin · 22 points · Posted at 13:38:43 on April 26, 2018 · (Permalink)
Hmmm sometimes it's just bad.
For my language, blz I've rewritten the parser 4 or 5 times.
That's because I learned something new everytime I did it and made a better product each time.
amazingmikeyc · 8 points · Posted at 13:44:14 on April 26, 2018 · (Permalink)
he does talk about that in the article.
panderingPenguin · 3 points · Posted at 14:55:46 on April 26, 2018 · (Permalink)
How large is that component though. There's a world of difference between rewriting a sub-100k SLOC personal project and a many million SLOC enterprise product.
🎙️ the_phet · 6 points · Posted at 13:47:43 on April 26, 2018 · (Permalink)
He speaks about rewritting the whole code from scratch, not parts of it.
MSgtGunny · 9 points · Posted at 14:09:05 on April 26, 2018 · (Permalink)
A parser can be a fully self contained program.
nikanjX · -6 points · Posted at 14:15:46 on April 26, 2018 · (Permalink)
So can a helloworld, but that’s not the issue discussed here
[deleted] · 1 points · Posted at 14:32:16 on April 26, 2018 · (Permalink)
But was that a commercial project, or something you did to learn from? Different goals.
blazingkin · 3 points · Posted at 14:37:48 on April 26, 2018 · (Permalink)
True, it certainly helped that I didn't have to meet deadlines. The rewrites were pretty necessary though.
__Cyber_Dildonics__ · 20 points · Posted at 14:28:43 on April 26, 2018 · (Permalink)
I don't think it is harder to read than write. I think people overestimate how difficult it is to read and underestimate how difficult it is to write.
Not only that, but tools for refactoring are poor in general and very poor in many languages. I want to at least be able to move variables around and have that changes trickle down to where they are used.
CrashOpa · 21 points · Posted at 16:09:21 on April 26, 2018 · (Permalink)
Reading code is relatively easy, understanding it isn't. As someone who's daily Job it is to plug holes in a 30yo codebase, most of my time is spend reverse engineering the code and figuring out what the purpose of the various parts is. And only something like 10% of the time am I writing actual code. Sure I can spot quite quickly what someone is doing in their code, but not why. And understanding that bigger picture in an existing project is harder then writing it. And crucial in order to improve on it.
SamSibbens · 3 points · Posted at 20:54:50 on April 26, 2018 · (Permalink)
Would you say commenting 'why' I do something a certain way would be good my own future self? (aspiring game dev here)
sfcpfc · 4 points · Posted at 21:42:08 on April 26, 2018 · (Permalink)
Yes, many devs would say that comments should be avoided in favour of writing self explanatory code (with descriptive function names, for instance), but some times that's just not possible. If why you're doing something isn't immediately obvious, comment the why.
(Not op BTW)
PlasmaChroma · 13 points · Posted at 18:28:23 on April 26, 2018 · (Permalink)
Reading good code is easy.
Writing good code is hard.
Reading bad code is hard.
Writing bad code is easy.
lustyperson · 1 points · Posted at 15:03:51 on April 26, 2018 · (Permalink)
I agree.
Writing code is more difficult and time consuming than reading it.
Writing code and the required tests is much more difficult and time consuming than reading it.
Writing code and the required tests and having it tested by users for days, weeks, months, years is even more difficult and time consuming.
Replacing existing code is difficult because it requires that the existing code must be read and understood first.
IMO the reasons for abandoning old code are:
- the old code has severe problems.
- the old code does no longer meet the requirements like e.g. being quickly usable and adaptable for a new project by new programmers.
webauteur · 8 points · Posted at 15:04:12 on April 26, 2018 · (Permalink)
This would have never been a problem if we had just stuck with COBOL.
KagakuNinja · 2 points · Posted at 20:31:48 on April 26, 2018 · (Permalink)
Pah. We write everything in MUMPS.
TheAscendedNinjew · 1 points · Posted at 20:24:03 on April 26, 2018 · (Permalink)
You like banks?
theQuatcon · 7 points · Posted at 20:44:06 on April 26, 2018 · (Permalink)
Joel is/was full of shit. He might have been right on some points, but even then it was probably just coincidental. Do not take anything he says/said without a huge lump of NaCl.
Source: I've actually had to use some of the software his company produced (still produces? I hope not). It was so far behind the times that it was completely unusable. It did truly absurd things like requiring Flash to show a chart -- they didn't even bother to just have the server render an image and then <img/> that sucker. (Not that that example is an example of being behind the times... just customer-unfriendly in the extreme. I can only apologize -- I'm traumatized.)
soviyet · 4 points · Posted at 16:21:08 on April 26, 2018 · (Permalink)
Maybe, but not in my world.
In my world, the old code was likely written by a team of guys in India that went through some 3 week bootcamp and have no business writing code professionally.
Or it was written by a contractor/freelancer that got in over his head and jumped ship because why wouldn't he? He got paid up until the point at whiOr his overlords started adding bizarre feature requests that were out of scope as if they were in scope all along and he quit the project in a state of complete despair.
Or it was written by a chain of coders who each left the terrible project for their own reasons, with no overlap so none of the multitude of programmers had ever had a conversation, let alone a meeting, and the glue holding all of that together was some ridiculous, technically illiterate "entrepreneur" who thinks he has enough of a handle on his system to explain it to me, the way he explained it to the last four coders, all of which did things in their own peculiar way with no common process or methodology whatsoever.
Sometimes the project was initially started based on either some really odd, outdated technology or some hip, new, and worthless technology, but at any rate, not the right technology and anyone with any experience would know that except, well, this team.
Or the code is just unreadable because writing readable code seems to be hard to do for a lot of programmers.
Consequently, I have never taken over an existing project in my life. Luckily, its 2018 and I don't have to. That's a really nice luxury to have.
Level21DungeonMaster · 1 points · Posted at 20:52:31 on April 26, 2018 · (Permalink)
You just described my company’s development philosophy except you missed the part where central aspects of the system are owned by different departments who don’t communicate or share a budget.
[deleted] · 4 points · Posted at 18:10:33 on April 26, 2018 · (Permalink)
What is your metric for determining whether code is “a mess”? If it’s hard to read then it’s a mess. that’s how I look at it. That’s a bullshit apologist fundamental law and I disagree. If it’s easier to write than to read, and I have to understand it and make it work, and (again) it’s easier to write it than to read it, then I’m not gonna read it I’m gonna write it.
techsin101 · 5 points · Posted at 19:34:26 on April 26, 2018 · (Permalink)
no old code is thrown away because it's harder to work with it and meet requirements then it's to write from scratch and swiftly meet current and future requirements.
Not only requirements change, but after following through with one strategy you start to realize its drawbacks and in place to design better system.
nobody will give you a reward if you managed to work with old code over someone who rewrote everything but was more productive in span of few years.
[deleted] · 4 points · Posted at 21:29:05 on April 26, 2018 · (Permalink)
Yo let's tag the Jagex moderators every time they mention spaghetti code and engine work.
fiskiligr · 4 points · Posted at 00:22:42 on April 27, 2018 · (Permalink)
Donald Knuth created structured programming. Then he created literate programming. I am still waiting for people to adopt the latter.
zodar · 4 points · Posted at 03:36:56 on April 27, 2018 · (Permalink)
I remember when this post came out. I wonder how many people will notice that it was written in 2000.
lavaeater · 1 points · Posted at 06:57:01 on April 27, 2018 · (Permalink)
Joels a smart guy, read him all the time back then
OvidPerl · 7 points · Posted at 19:53:39 on April 26, 2018 · (Permalink)
I'm a consultant. I get called in over and over to help companies when their back is against the wall. I've seen plenty of these rewrites. They're usually an unmitigated disaster. Part of this is because I find that many developers really don't have a good understanding of how to fix legacy code. Instead, they say "the system is too unmaintainable and we need a rewrite." (And they usually believe it).
Rewrites are shiny and sexy and management, often lacking the deep technical knowledge, buys into this argument. What's worse, in one of the most risky things a business can do, the decision is almost always made on emotion rather than with a solid business case (cost analysis, risk analysis, alternatives, opportunity costs, and so on).
The primary arguments for a rewrite go like this:
Let's take those in reverse order.
You can sometimes find yourself with code that simply can't do what you want it to do. More than once I've seen Node projects rewritten in Go because Node, while great, simply doesn't handle CPU-intensive tasks well. Or that client who decided their code needed to be peer-to-peer instead of client-server. That's also a strong candidate for a rewrite. This happens sometimes, but having an insurmountable technical issue usually isn't the driving force in rewrites. Most of the time I find awful code that can still get the job done and it would take less work to fix the code than to rebuild an entire system from scratch.
If your code is written in Haskell or Smalltalk, both awesome languages, finding developers is hard, particularly if you want them to move to a small town in the middle of nowhere. If you rewrite to PHP or Java, finding developers usually isn't a problem. However, by definition, languages with a small developer base are less common, so fewer companies have this issue.
True story: I love the one company who called me about maintaining their Perl system after they decided to rewrite their flagship software in Java. The Perl system was earning them tens of millions of euros and had hundreds of customers. Two years into their rewrite, they were able to shift two of those customers to the Java system and they weren't developing new features for the Perl system. What's worse? Turns out that the problems with the Perl system were due to hiring devs who didn't understand architecture or databases. It probably would have taken about six months to fix the most pressing needs because they weren't facing that serious of a problem, but hey, rewrites are sexy!
That being said, sticking to less popular languages could lead you into technology lock-in.
For the "easier to maintain code", that usually depends on the cleaner architecture. But here's the rub: either you take the devs off the old code and put them on the new code, leaving the old code essentially unmaintained, or you hire new developers with less business knowledge and drive up your costs. In either scenario, capacity planning is a nightmare. The larger the system, the more likely it is to fail.
And so management starts to get worried, pushing the devs harder, and that nice, clean architecture gets worse and worse as "temporary hacks" become permanent and unclear specifications get implemented without understanding the consequences. Congrats! You're exchanging one pile of spaghetti for another!
I've seen this again and again and again. Companies go bankrupt over this. I have one client who only avoided bankruptcy because three years into their rewrite, they had managed to buy up several highly profitable companies. They eventually transitioned out of their core business due to that rewrite mess and relied on the profits of the companies they purchased.
And the icing on the cake? The larger your project, the more likely it is to fail:
Seriously, why would you honestly pitch a rewrite when you know it's such a high-risk proposition if you can fix your existing issues and still have working code? Large projects fail all over the place and rewrites hurt companies!
Pro-tip: if you're a developer who's facing management that's dead-set on a rewrite even though you know you can fix the issues, don't say the word "refactor." It's become a toxic word to many people and can trigger strong emotions. Instead, agree with management and explain to them that to minimize risk, you want to keep the old system running while you do an "in-place rewrite." It can work wonders.
amalik87 · 1 points · Posted at 17:18:59 on May 23, 2018 · (Permalink)
You sound really smart.
tsmc · 6 points · Posted at 14:58:05 on April 26, 2018 · (Permalink)
My rule: write your code for junior developers. This means not taking full advantage of all the features of a language just because you can, and if something is actually an objectively better design decision then drop a comment on why it is so. Sometimes I even insert an archived URL to the docs for the feature. I’ve gotten dinged for made-up code smells like “primitive obsession” (yes, this is a thing) but at the end of the day I am not seeking to fully express my creativity, I am not a craftsman, and there’s likely another human who will have to deal with my code under tighter constraints than I had.
blackholesinthesky · 3 points · Posted at 20:09:31 on April 26, 2018 · (Permalink)
I'd be cautious of this. How is a junior developer expected to grow unless they are introduced to new ideas/patterns? On top of that some junior developers just don't know the fundamentals of the language, or any language. I've worked with people who don't understand how to use
map()I'm always going to pick:
over:
The first is harder for a junior dev to read, but a senior dev can read it and understand whats happening more concisely. With the each loop I have to interpret what you're trying to do, with the map I know exactly whats being done
tsmc · 2 points · Posted at 22:27:44 on April 26, 2018 · (Permalink)
I think it's completely clear what's going on in each case. One is a few more lines of code, most of it bookkeeping that even a newbie should absorb at a glance. I'm not sure how well this would hold up for a nontrivial example. You do raise a good point regarding introducing juniors to new ideas. I've never been good at mentoring.
rush22 · 1 points · Posted at 23:02:46 on April 26, 2018 · (Permalink)
I wrote an internal tool that uses a single table Access database as the backend for this reason. It's only used by 4 or 5 people and the fact that I can say "Just install Access and open the file. Read the help of you need to." to any junior dev if something in it needs to be fixed is 10x more valuable than the slight performance hit and somewhat arcane, but well documented and supported, queries.
[deleted] · 1 points · Posted at 23:18:40 on April 26, 2018 · (Permalink)
What, like using int instead of IntegerFactory.createInteger(new IntegerBuilderImpl().addOneHundred().addTen().addOne()) ?
tsmc · 1 points · Posted at 23:37:02 on April 26, 2018 · (Permalink)
That's the pathological case :) My reviewer's complaint was that I did not use classes to couple data and operations on the data, I used free functions on primitive data structures.
MpVpRb · 3 points · Posted at 15:36:10 on April 26, 2018 · (Permalink)
I would restate it as...
It's easier to create complexity than it is to understand it later
The code always ends up more complex than the original design
Most of the time it's because the initial design was incomplete, but it can also be that the programmers didn't think of the simple solution. Other times, after a large bunch of working code is in place, a change is required that doesn't fit. The adaptations and workarounds introduce more complexity
WillAdams · 3 points · Posted at 16:08:37 on April 26, 2018 · (Permalink)
Literate Programming anyone?
http://literateprogramming.com/
Ironfist · 3 points · Posted at 16:18:38 on April 26, 2018 · (Permalink)
My old code is a mess. As time goes on you get better at programming which means you'll see new ways to refactor or optimize things.
Snoron · 2 points · Posted at 18:37:55 on April 26, 2018 · (Permalink)
That is usually the case, yeah... but every now and then I see an old function I can barely understand, but after some annoyance with working it out I realise how damn clever it was and I think goddamn how did I ever even come up with that, I'm a genius! :P
morphotomy · 3 points · Posted at 16:56:16 on April 26, 2018 · (Permalink)
Code should not be hard to read.
[deleted] · 1 points · Posted at 17:26:50 on April 26, 2018 · (Permalink)
[deleted]
morphotomy · 7 points · Posted at 18:55:31 on April 26, 2018 · (Permalink)
Just took a cursory glance at the netcat base. I don't completely understand it all, but it seems to be broken out into atomic functions that have sane and descriptive names.
If I had to work on this codebase, I could probably contribute something useful within a week or two. Not the case with the application I'm currently working on.
PM_ME_UR_OBSIDIAN · 3 points · Posted at 17:00:36 on April 26, 2018 · (Permalink)
IMO: functional programming à la F# and friends is about shifting the balance of the work towards the author and away from the maintainer. That's what makes it valuable.
LetsGoHawks · 0 points · Posted at 18:11:09 on April 26, 2018 · (Permalink)
So your assertion is that functional programmers will always write great, easy to read code that works well all the time and there will be little need to fix or modify it forever and ever amen.
I disagree.
JoseJimeniz · 3 points · Posted at 17:08:11 on April 26, 2018 · (Permalink)
One thing I wish I could have told my younger programmer self is to not attempt to turn this one-off solution into a full generic solution for the next time someone has a similar problem.
Because as you start to make it generic, you have start to leak your abstractions - requiring everyone to understand everything about your solution before they can plug into it.
The useful shared code is very small library type functions.
Otherwise it's sometimes easier to simply start over.
For one project I wrote what I thought was a very minimal framework. Very basic functionality. Very simple model. The next time I wanted to use it, I realized I could rip out half of it. I quickly forked my own code, and created an even more minimal version.
Tldr: don't write the complicated framework
colly_wolly · 2 points · Posted at 17:20:56 on April 26, 2018 · (Permalink)
I think code reuse is pushed in university. I saw an interesting article the other day. Don't have code reuse as a goal in itself but do avoid code duplication. I think that gets to the point quite well.
[deleted] · 3 points · Posted at 17:57:07 on April 26, 2018 · (Permalink)
Well actually no. I also thought it's normal to always think your old code sucks, but I've reached a point where I find my old code pretty good, reusable, and readable. Going back 6-7 years even. I'm in this business for 20 years.
I do sometimes have to rewrite or extend it in parts, but that's normal, because requirements change and so the code may change. That's true not just for old code, but also new code.
I think people who constantly find their old code sucks have more to learn about reuse, and clean factoring and architecture (no I don't mean Clean Architecture TM but just architecture that's clean and modular).
The same applies for third party code. I don't find that all 3rd party code sucks. Some is really well factored and a lot of thought was put into it. But a good chunk of 3rd party code sucks simply because the people who wrote it were not experienced enough to write good code, and it's very easy, to me at least, to be specific about advice and feedback about where someone failed in their code in objective ways.
At some point it's not just about PoV or the difficulty of reading code. It's about the experience of the writer.
datchilla · 3 points · Posted at 17:59:03 on April 26, 2018 · (Permalink)
I played a game called factorio with a friend.
Factorio is a logistics game where you connected different widget machines together via conveyor belts. Late game the map can look like spaghetti.
When I played with a friend we would make machines then alter them to fit a certain need. But when it came time to modify the setup so we could scale the machine up ny friend would delete everything and start building from scratch with a bigger size in mind. He would do this even if I had made space to make the machine 2x-10x larger.
For him rebuilding from scratch was easier than spending a couple minutes figuring out how the original machine worked.
blind99 · 3 points · Posted at 17:59:05 on April 26, 2018 · (Permalink)
Funny, cause I just made a call to rewrite old code base from scratch. I had a Borland Turbo C codebase for MS-DOS written in 1995 to port to a modern Linux system with multiple changes in terms of functionalities. Old code probably was not shit but it sure looks like it from today's perspective. Who here would have tried to port instead of rewrite?
addicted2weed · 3 points · Posted at 18:28:37 on April 26, 2018 · (Permalink)
Jesus Christ, does noone use git?
michaelochurch · 3 points · Posted at 20:35:39 on April 26, 2018 · (Permalink)
This is true, but it's also sociological. Maintenance has low career value and makes it hard for a programmer to justify himself, much less get a transfer to a green-field project. You often see engineers who get stuck on legacy maintenance, don't really distinguish themselves because they can't, and have to change companies if they want to write something new. But another way to get a better job, if you're good at politics, is to try to create one, which is why there's always a push to do it again and better.
It's also true that 99+ percent corporate code is unmanageable garbage. The problem is that, if the new system is written under the same deadline pressures as the old one– and often it is, if not under more deadline pressure since it's replacing something that already exists and seems to work– then it will be junk just like what it replaced. So, the temptation to rewrite it is strong, but it's exceedingly rare to have an executive climate that makes good code possible in the first place, so usually this involves replacing one pile of crap with another pile of crap.
blackmist · 3 points · Posted at 21:02:08 on April 26, 2018 · (Permalink)
I'm working with a 15 year old code base. Fucking kill me.
all_mens_asses · 3 points · Posted at 00:15:52 on April 27, 2018 · (Permalink)
There’s another fundamental law: Most programmers are mediocre (by definition), and they’re given ill-defined requirements with impossible deadlines.
deong · 3 points · Posted at 00:18:33 on April 27, 2018 · (Permalink)
I quibble on a detail. They're not probably wrong. They're very likely right. The old code really is god-awful. The mistake is thinking the new code won't be. Code doesn't age well. Comparing it to a Dodge Dart is facile, because the Dart is a car very much like every other car ever built. It doesn't need to change every month to support a new kind of road, petrol, atmosphere, and drivers who are suddenly 20 times bigger or smaller, and as a result, you don't need a specialized group of people whose job it is to always understand exactly how to alter it at the near molecular level. Any old mechanic will do, because it's the same as any other car and it just has to do car things.
Software is different. Working on Excel doesn't even prepare you for working on Lotus 123, let alone some custom banking software and World of Warcraft. Every piece of software is declared finished with no more than a handful of people in the world who knows how that piece of software works. The code doesn't rust, but those people's memories and employment statuses do.
That's why there's so much appetite for rewriting. Because you aren't one of the people who really knew how it worked, and over the years, it's been hacked at by people like you who didn't have that picture in their heads until it's held together with duct tape and gum. The problem is in thinking that the new version will be better. It may be better for you, because you get to be the guy who understands it all now, but over the lifetime of your code, the outcomes look the same. And you had to reinvent 20 years of bug fixes to get there.
is_it_fun · 3 points · Posted at 02:58:19 on April 27, 2018 · (Permalink)
Maybe if people FUCKING DOCUMENTED THEIR CODE we would be having a very different discussion. No, no, no you troglodyte, it doesn't 'explain itself.' No you horrible horrible person it does not! Code comments exist for a reason!
rashnoy · 1 points · Posted at 04:19:57 on April 27, 2018 · (Permalink)
I like this guy :D
mikeymop · 1 points · Posted at 06:43:46 on April 27, 2018 · (Permalink)
I'll even be happy with an .md that just briefs a little on each function it class or structure. It'd be so much faster than interpreting
lavaeater · 0 points · Posted at 06:57:27 on April 27, 2018 · (Permalink)
Code comments are shit.
[deleted] · 2 points · Posted at 19:46:33 on April 27, 2018 · (Permalink)
An Uncle Bob zealot detected.
is_it_fun · 1 points · Posted at 21:53:40 on April 27, 2018 · (Permalink)
Whatevs.
carleeto · 3 points · Posted at 07:59:16 on April 27, 2018 · (Permalink)
Joel makes one big assumption - that the developers behind the original codebase actually were competent.
The worst of the technical debt I've seen is of the type where the programmers reinvented the square wheel - for example, instead of using normal time synchronisation, they wrote their own server and client and then proceeded to reinvent a system to represent daylight savings, because they had also decided to store everything in local time.
The code then "grew hairs" not because of bug fixes, but rather because the original developers were too stupid or lazy to use a proven standard that existed when they wrote the code, because they didn't do their homework.
Sometimes the root cause has nothing to do with bug fixes or edge cases. Sometimes it really does need to be thrown out because the foundation is plain old incompetence.
mgkimsal · 2 points · Posted at 11:44:03 on April 27, 2018 · (Permalink)
I've thought this for years on this "joel says not to throw out old code!" topic. I've come across projects where I advocated throwing everything away and starting from scratch, then ... sometimes regretted that decision (sometimes not). There were times when I talked myself out of a 'start over', and just worked with what was there, and... lordy, that approach was almost always a losing approach (except for very trivial situations).
There's other assumptions that Joel seems to make:
That last one has bitten me the most.
I've taken over projects from other people who are no longer on the project (or perhaps even with the company, or in some cases, not even alive any more). When taking a 'keep going and make mods' approach, what I usually come to find out is that I start getting more and more bug reports about stuff that never actually worked before, but it was never acknowledged by any one.
I was brought in to do a migration on a system 2 years ago. The second part was to 'fix a couple bugs'. Once I got talking to the end users, I got a flood of requests. "You're the first person we've talked to in 3 years who's ever been able to fix anything, ever".
Some were not even huge fixes. Click a button to download a PDF file - broken. Oh... hey - the person who wrote this did not understand what HTTP headers were and just dumped raw binary data from a file. Probably worked on IE7 when they first wrote it, maybe, but ... whatever.
There was little hope of rebuilding that from scratch, but also little hope of ever actually understanding the entirety of the codebase (which was, IIRC, hundreds of thousands of lines of codeigniter PHP). No runnable tests (there were a few, but it was some homegrown test tool - the few docs written years ago didn't work).
So... I was 'too expensive' to keep working on this, and it was offshored to a support team in eastern europe (with a stateside management team). I got a call about 6 months after that from the primary end-user client, indicating nothing of substance was still done, they were unhappy, etc.
This was not necessarily a situation where "rebuild!" was definitely a correct approach. TECHNICALLY, yes, but politically and businesswise, no. But... the management team had 0 idea how bad it actually was (there was no official issue tracker anywhere to keep track of things), and once you got in there, you realized it was really more bad than good.
So yeah, this idea that systems are always in a state where just dedicated refactoring is the 'right' answer may be a good starting point, but IME is not a universal truth.
Oh... yeah, other idea here. Or security. Trying to retrofit secure practices in an existing spaghetti codebase is a nightmare, and a real liability. I've dealt with more than a few systems were I advocate rebuild simply because I have no confidence that I can address glaring security holes in a cost-effective manner. And... if I am now on the hook for dealing with someone else's security issues, the stakes, for me, are too high to accept. I'm primarily coming in as a contractor/consultant; if I was being hired in to a permanent (heh) team for a full-time role, that might be a different story.
Madoka_the_Goddess · 3 points · Posted at 10:21:44 on April 27, 2018 · (Permalink)
To be fair, some of my code is a mess.
PompeyBlue · 3 points · Posted at 11:06:45 on April 27, 2018 · (Permalink)
I just tried an interesting experiment. I asked two junior programmers, 1 year experience each, been in my company for same amount of time to do the following:
Programmer 1
Write me a function which takes an array of integers, and the number of integers in an array. IFF the sum of integers, and number of integers, are both even then return 1. IFF the sum of the integers, and number of integers are odd then return -1. Otherwise return 0.
Results
Programmer 2
Look at this function, explain what it does.
Conslusions
The Function written by programmer 1
mgkimsal · 2 points · Posted at 11:23:46 on April 27, 2018 · (Permalink)
curious as to why comments were not a requirement. or any sort of unit test. it would have taken longer to write, but probably less time to read and comprehend, no?
Michaelmrose · 1 points · Posted at 18:47:24 on April 27, 2018 · (Permalink)
It's bad code in a bad language with no comments and zero context.
Why would someone have to pass in the quantity of numbers instead of examine said numbers. Further its confusing to me that anyone could have not heard of % OR figure out at least that its called an operator and google % operator.
Just making a function called odd and even would have made it clear what the % was for and a comment like your explanation above would have made it crystal clear what the purpose was.
Your test mainly shows the cost of writing bad code.
Michaelmrose · 1 points · Posted at 19:27:24 on April 27, 2018 · (Permalink)
In clojure
or
Zorb750 · 3 points · Posted at 12:28:37 on April 27, 2018 · (Permalink)
You need to know when to throw away old code. Failure to do so it's a major factor contributing to code bloat and bugs.
DonLaFontainesGhost · 3 points · Posted at 12:48:14 on April 27, 2018 · (Permalink)
I've always felt that it's more a case of "Yes, the code is a mess" because once in production all code is a mess. We come up with these nice abstract models that satisfy 98% of the requirements, and then we start coding edge cases in response to bug reports - and that's where all the sloppy bits and pieces come from.
New developer shows up, looks at the codebase, has a mental model that's pristine that handles ... 98% of the requirements, and thinks "I can replace this mess with a much cleaner model" and they do
...and then they start coding the edge cases in response to bug reports...
Back in 1998 I was working with an Oracle DBA who loved Oracle's CASE tools, but she knew that at some point she would always have to start writing code, at which point she couldn't use the CASE tool any more, because the round-tripping would be broken.
We had a pool on how long into a project she could get before breaking the CASE tool...
thinsteel · 3 points · Posted at 09:27:16 on April 28, 2018 · (Permalink)
Nah, they're probably right. The old code is a mess. Where they are wrong is in assuming that the new code won't be a mess.
minionslave · 5 points · Posted at 14:27:52 on April 26, 2018 · (Permalink)
In my experience, what I have started doing is incrementally improving. First starting with better variable names, better loops, better data structures within the function. Shorter functions, then changing the class.
Then you do that over and over, and the code basically refactors itself, a cleaner architecture shows up.
tonefart · 7 points · Posted at 13:46:12 on April 26, 2018 · (Permalink)
It's because of the forever changing trend and patterns and frameworks that comes and goes. If code is all pure logic it should never be an issue, but if framework of the day comes and goes, you throw away a lot of old code. How many here had to throw away Angular1 code?
piexil · 1 points · Posted at 14:54:31 on April 26, 2018 · (Permalink)
what about anybody who wrote anything with polymer, talk about something that just came and went.
Swie · 1 points · Posted at 15:31:51 on April 26, 2018 · (Permalink)
That's part of it, but also as a project progresses unforeseen requirements and problems are added, or change in importance. You can write a design that worked really well for your original predictions of what you would need to support, but after X years what you need to support may have changed dramatically so your design must change as well.
Or sometimes the features didn't change that much but the programmer's understanding of the required logic/design did.
ltjbr · 1 points · Posted at 16:33:59 on April 26, 2018 · (Permalink)
That's why it's always risky to go with the latest and greatest for any substantial project. Code Slingers might be frustrated by not doing the "cool stuff" but some times that stuff is only a fad. Now you're left with a poor front end stack no one likes solely because it was the hot tech at the time.
Smart companies have the guts to say no to the devs pushing for cutting edge tech.
Some devs might leave, but that's not necessarily a bad thing. You want devs that care about what's being delivered and work well with others, not devs that care about hip frameworks.
Euphoricus · 9 points · Posted at 14:28:16 on April 26, 2018 · (Permalink)
Incorrect. The problem with legacy code is that it is hard to know if any change will not introduce a regression. It is impossible to know and test for all possible edge cases with legacy code. Even with perfectly readable and understandable code, there will still be edge-cases that are not obvious.
Which is why I love Feather's definition : "Legacy code is one that doesn't have automated tests". With automated tests, it doesn't matter if code is unreadable mess. It becomes trivial to experiment to figure out intended behavior and then refactor to improve readability.
dpenton · 6 points · Posted at 16:18:44 on April 26, 2018 · (Permalink)
This assumes that the existing tests cover what you change. I see it every day when a whole family of tests exist for something, and the unknown unknown happens. Meaning a new test case didn't exist, or a component failed in a way that "should not have happened". Regressions can happen whether the code is "legacy" or not. The definition of legacy code:
FlyingRhenquest · 1 points · Posted at 22:07:41 on April 26, 2018 · (Permalink)
Seems like one solution to "This code's crap and needs to be rewritten" from every new dev on the project would be to put new devs on the project to work improving unit test coverage. They get to write new code, they get familiar with the requirements and they get familiar with your code base. At some point they should start to realize why the code base is like that, and maybe they find and fix some actual bugs in the process.
Notorious4CHAN · 4 points · Posted at 15:10:34 on April 26, 2018 · (Permalink)
Maybe it's just the book on software architecture I've been reading lately, but it seems to me that the biggest issue with crappy old code is the fundamental design. And if the design is shit with all kinds of circular dependency graphs, there is going to be huge technical debt that is going to impact future development. If you don't at some point redesign you are going to continually spend more development hours making less progress.
If something can be trivially addressed by a simple refactoring of a couple functions or classes, great. But I've seen a lot of applications written by developers (with a primarily procedural background) who haven't given any thought to architecture - only to delivering the product requested today as fast as possible, and when those applications get to be nearing 10 years old they are incredibly fragile and full of inscrutable code.
Even some of the best developers I know make shit architectural decisions in the name of productivity. Because you have to write 20x as much code to do things the right way when you can just insert this single line of business logic into the UI. But when you start inserting code anywhere you can make it work rather than the right place you are setting yourself up for a maintenance nightmare. The is the flip-side of "pragmatic programming" - it is important to be able to get the job delivered on time, but if you don't immediately turn around and do it the right way and the next developer comes along and creates a dependency on having done things the wrong way you have a mess on your hands. If there is too much pressure to deliver too fast, this is going to happen every time. Do this enough and a rewrite is the only way out, and the alternative is to pay 5 senior developers to deliver what one junior developer could in the same time without all that technical debt to contend with.
yashchand · 4 points · Posted at 17:21:14 on April 26, 2018 · (Permalink)
Without reading these comments I know half are people saying "but not me"
moreintense · 2 points · Posted at 13:39:48 on April 26, 2018 · (Permalink)
Depends on the programmer. Some get a concept working, then refactor. Sometimes you learn new practices and you inherently want to update old code. Some just shouldn't code.
Manitcor · 2 points · Posted at 14:59:30 on April 26, 2018 · (Permalink)
It takes experience to know the difference between code that is difficult to read and bad code. Sometimes unreadable code alone is enough to refactor since code should be a document for other humans first. The only time you should stray from that is when you are forced to do odd things for optimization's sake. Then you just write a one paragraph comment apologizing for the hell you have created.
againstmethod · 2 points · Posted at 15:00:27 on April 26, 2018 · (Permalink)
Really?
They didn't bring anything forward? I find that odd.
I often rewrite code, but i bring forward my good bits. And i do it because ive learned more since the last time i worked on the project in question and know whats wrong with it.
david · 2 points · Posted at 15:03:58 on April 26, 2018 · (Permalink)
I think the main problem is that we judge existing code on its achievements, but the planned rewrite on our aspirations.
There are times when a rewrite is the best solution, but it's hard to make a balanced assessment
elcubismo · 2 points · Posted at 15:15:17 on April 26, 2018 · (Permalink)
On more than one occasion I've rewritten a function that I felt needed to be redone, only to compare it to the old one and realize it was pretty much the same thing.
lykwydchykyn · 2 points · Posted at 15:38:01 on April 26, 2018 · (Permalink)
Where I work, I am "the developer" -- nobody else is writing code. I tell my coworkers that someday when I retire, quit, or get the axe, whoever they get to replace me is going to tell them that all my code is crap and they'll need to rewrite it from scratch.
That person will probably be half-right, if only because (1) I'm human, not a coder-god and (2) technology will probably advance and there will be simpler ways to do what I did.
Even so, when that day comes, I have no qualms about that person doing whatever they feel they should do, because at that point, the code is their problem, and they have to live with the choices, not me.
LetsGoHawks · 1 points · Posted at 17:38:10 on April 26, 2018 · (Permalink)
Similar situation.
You now what got me past the urge to rewrite everything written by those who came before me?
Actually rewriting some of it.
Now? If it ain't broke, I ain't fixing it. I don't care how shitty the code is, and some of it is really bad. It gets the job done and that's good enough.
Every now and then I'll end up rewriting small sections as part of another project, but only when it's quick and makes sense to do so in the context of the project. But that's it.
lykwydchykyn · 1 points · Posted at 18:16:28 on April 26, 2018 · (Permalink)
I rewrote a lot of my predecessor's stuff, but not because it was bad; mostly because it was small stuff that was written on an unfamiliar (or very dated) stack, or because the scope had changed and the original tech wasn't appropriate any more.
I didn't throw him under the bus, though; I always maintained that his code was great, but we just needed a rewrite. And truthfully, it was worth a few weeks of rewriting to be able to spend the next ten years maintaining my own code and designs.
ctorx · 2 points · Posted at 15:51:52 on April 26, 2018 · (Permalink)
It's easy to look at an antiquated piece of software and think you can bust out a newer better version but you are almost always wrong.
I have found that when I'm having the desire to rewrite something it's usually because I'm too lazy to dig in and wrap my head around the existing logic flow, which is often a long, cumbersome and confusing journey comprised of numerous iterations.
Almost always, once I have wrapped my head around the legacy software it's clear that there is nothing fundamentally wrong with it and that my disdain comes from the fact that it does not match my current idea of what good software looks like.
LetsGoHawks · 1 points · Posted at 17:46:47 on April 26, 2018 · (Permalink)
It's too bad this comment is so far down and will get mostly ignored.
As I told somebody else, the only time I'll rewrite stuff is when A) It's won't take too much time B) It makes sense to do so in the context of what I'm working on and C) I'm extremely certain that the new code will be a lot better.
Otherwise, if it's hard to understand, I just try to remember to add some comments.
sonstone · 2 points · Posted at 16:58:09 on April 26, 2018 · (Permalink)
It doesn't help that the old code was a mess.
Zarutian · 1 points · Posted at 20:38:12 on April 26, 2018 · (Permalink)
something thrown together with gum and bailywire? That is often the impression.
serial_crusher · 2 points · Posted at 17:46:36 on April 26, 2018 · (Permalink)
Ehhhh, this is a pretty optimistic view of things. Old code wasn't carved in stone and sat there in production being perfect for decades. Old code had bugs that needed to be fixed. And people didn't fix those bugs perfectly and flawlessly. They stacked band-aids on top of band-aids and made the code shittier as they went.
The old code isn't "proven and flawless". It does the things the production environment demanded of it, but that's not what it was designed to do or what you want to do with it now.
So yeah, sometimes you have to decide between putting another band-aid on it or replace from scratch. Two hard choices, but eventually it has to be done.
NoMoreNicksLeft · 2 points · Posted at 17:58:58 on April 26, 2018 · (Permalink)
This is one of those arguments that sounds insightful, superficially.
But how many large systems did he personally examine before making this claim? Was it hundreds? Surely not thousands. Was it dozens? Was it two or three? Were they even that big or old?
Some of the code I maintain and modify has comments in it from the early 1990s. That's not bragging, fairly certain more than a few people could one-up me by decades. But it's old and big and there are single-source-code-file applications that are 30,000 lines or more of spaghetti.
I don't want to start over. That's insanity. I'd like to rewrite it while dissecting the original on the pathology table right next to the new model. Go over it line by line maybe.
Fuck, the wonders I could do if I could just get rid of the comments and chuck those into git commit messages. Or to get rid of commented-out-code.
Actually though, I don't care enough about this shit to want to do that. I'm talking more theoretically like in some ideal job where it matters. It's all bailing wire and duct tape here.
Retardditard · 2 points · Posted at 18:05:25 on April 26, 2018 · (Permalink)
Hell fucking no.
Writing bug-free code is a herculean task.
Reading well-written code is like: oh, that's fucking obvious.
gjallerhorn · 1 points · Posted at 18:23:59 on April 26, 2018 · (Permalink)
You're comparing opposite ends of the spectrum. Writing mediocre code is easier than trying to read through it
Retardditard · 1 points · Posted at 18:40:42 on April 26, 2018 · (Permalink)
Notice how every piece of software mentioned is basically now irrelevant to non-existent?
Code reuse isn't hard. That's why we have libraries, DLLs, objects, and so forth. It makes it easier.
Fuck functional programming!
There's your problem.
Again. If you don't understand your fundamental libraries... nothing is going to fix that besides learning them. A lot of programmers waste time writing functions for APIs that are vastly superior to them. And it is hard to understand, literally.
Of course it rusts. 32 bit code is junk. 16 bit code is utter garbage. 64 bit is king!
This was written before 64 bit processors. So I'm just going to digress from here on out.
edit: btw, I totally agree. Jibberish code is what I call it. Reading shitty code is shitty. Then again, plenty of software has been rewritten from the ground up. Case in point: 9x vs NT. Fan-fucking-tastic! The only way to truly evolve is to start over. Maybe not entirely, but certainly predominantly.
Speaking from experience: my best improvements to my own algorithms have been when I started over. When I looked at my code and concluded: this does not work. I started fresh. I asked other programmers for input. I got ideas for vastly superior algorithms and used them and the results vastly improved and the efficiency vastly improved. And typically reading the code... yup! that improved, too.
maxdifficulty · 2 points · Posted at 18:20:48 on April 26, 2018 · (Permalink)
Throwing away code can certainly be worth it. For instance, your codebase may be so bad that rewriting it would save you a great deal of time and money down the road. Obviously, this is easier said than done -- the new code may wind up being just as bad as the old (unfortunately, most software engineers are awful at architecting).
And I think it's a bit disingenuous for the author to suggest that Netscape's decision to rewrite their code has caused their market share to decline over the past 3 years. I mean, it's probably been 10 years since I last thought about Netscape or heard anyone mention it, so how many users could they have possibly lost?
ThatThingAtThePlace · 2 points · Posted at 18:25:04 on April 26, 2018 · (Permalink)
People need to keep in mind that this article was written 18 years ago. It's more relevant now as a sign of the times than as a guiding principal.
CarthOSassy · 2 points · Posted at 18:25:47 on April 26, 2018 · (Permalink)
I have maintained this awareness on my current project by sheer force of personality.
So far, my experience has been that: we've moved from throwing away 100% (and copying 50% back in); to throwing away closer-and-closer to 50%, over time.
We seem to actually move marginally slower, but we, so far, have not introduced any defects into release. That is a depressingly massive improvement.
All in all, the difference is frustratingly less than I'd hoped, but positive. I think as we emotionally accept this approach, things may improve even more.
OuTLi3R28 · 2 points · Posted at 18:34:09 on April 26, 2018 · (Permalink)
That's why the best programmers are the ones who can read, analyze and think in code.
rageingnonsense · 2 points · Posted at 19:05:26 on April 26, 2018 · (Permalink)
A lot of this makes sense, but there are occasions where you really do have no choice. There may be a few reasons, but the one reason I can think of off the top of my head is that your application may have outgrown its underlying tech.
For instance, you may have written an application in a scripting language, found that it has outgrown that and now needs to be written in a language that can be natively compiled. It doesn't matter why it started in the scripting language (maybe it was short sighted thinking, maybe the growth was not expected when it was conceived, who knows).
Other than that though, I agree with this post. A perfect example is Blender. It has a very complicated and unwieldy codebase, and the first instinct when you work with it is that you want to throw it away and start from scratch. But, at the end of the day, that 20 year old unwieldy codebase produces a fantastic product that gets the job done. The end user does not care what is going on under the hood, just that it does its job well. Any problems with that codebase can be fixed with comments and a bit of reorganization; no need to throw it away.
[deleted] · 2 points · Posted at 19:34:01 on April 26, 2018 · (Permalink)
Well that's just not true at all.
GunnerMcGrath · 2 points · Posted at 19:52:21 on April 26, 2018 · (Permalink)
I'm reading that article just thinking, these programmers you're talking about must not be very good. Everybody writing their own string splitting functions? Code reuse is hard? Come on.
Also, every system gets built and then added onto over time. Eventually all those additions to hack in new features that were not part of the original design start to create a mess. At some point you've learned a lot, technology has improved, you have a clearer vision of what the application needs to do, and there are plenty of places where things could work much better if they were designed to work together.
Of course starting from scratch will have challenges, not the last of which is trying to make sure the new app does everything the old app did, and catches all those word cases you codes for but may not have documented (though there are ways to mitigate this). But that doesn't mean it's stupid.
Just make sure your developers are competent enough to do the job.
Edit: this article is 18 years old. I thought the mention of Netscape was weird but I didn't catch it at first. A lot has changed in 18 years. No wonder his developers sounded stupid.
thecrius · 2 points · Posted at 20:04:31 on April 26, 2018 · (Permalink)
This is only true for the age we are in development in which most old projects comes as monolithic wall of text spread across few files.
Even when they are done using an mvc framework, the probability of the original programmer not following the guidelines and writing a mess of hacks and workaround because it didn't want to waste time reading the doc (or the doc being missing) are very high.
This is also the main problem I find in JS framework. Most of the framework make a pride of being unopinionated but considering that the disciplined developers are quite rare, that's not really a plus in my book.
Lately I'be given a round to Angular and Vue, working in a company that used exclusively AngularJs. I found Angular to be quite promising in giving direction and kinda forcing the Devs to follows a path. This if you use the excellent CLI.
Vue is quite interesting, the only thing I find bothering is that the CLI seems to only create components in a single .Vue file, which is interesting if you're writing a web component but not much of you're writing a complex frontend application imho.
All in all, CLI and blueprint are the saviours imho.
saijanai · 2 points · Posted at 20:38:22 on April 26, 2018 · (Permalink)
And sometimes, old code really IS a mess.
agumonkey · 2 points · Posted at 20:44:36 on April 26, 2018 · (Permalink)
Not my opinion at all: it's harder to perceive the full extent of the problem, therefore the code looks like senseless crap.
[deleted] · 2 points · Posted at 20:54:57 on April 26, 2018 · (Permalink)
If it's fucky, I'll rewrite the fucky parts. No reason to flip the table over.
BobSacamano47 · 2 points · Posted at 20:55:08 on April 26, 2018 · (Permalink)
While this is probably sometimes true, I can't comprehend how a human can be so dumb to just generalize all situations like this. And these are the "thought leaders" of our world.
AvantAveGarde · 2 points · Posted at 20:55:54 on April 26, 2018 · (Permalink)
Joel’s book is really good I highly recommend reading it on your spare time
MrShekelstein26 · 2 points · Posted at 20:57:27 on April 26, 2018 · (Permalink)
idk man, my old code is pretty trash.
TheAmazingGazza · 2 points · Posted at 20:58:35 on April 26, 2018 · (Permalink)
Also, comment your codes. You might understand it, but not the one who follow up your code a few year down the line.
Procrastanaseum · 2 points · Posted at 21:15:28 on April 26, 2018 · (Permalink)
I was watching "Antitrust" on Hulu the other day and had a good laugh over the HTML floating in the background of the opening credits. Then later on in the film, the characters would cream themselves after looking at code for a split second, saying how amazing it was. Hollywood coders are hilarious.
pure_x01 · 2 points · Posted at 21:33:40 on April 26, 2018 · (Permalink)
There is also this fact that it's fun to write code from scratch.
[deleted] · 2 points · Posted at 21:43:25 on April 26, 2018 · (Permalink)
I usually start over when the underlying architecture can’t support scalability with capacity and new feature support. Or when I’ve added so much spaghetti code, it’s now unmanageable.
I don’t think I agree with this premise.
TheDevilsAdvokaat · 2 points · Posted at 21:46:15 on April 26, 2018 · (Permalink)
I really don't agree with this at all.
I often find I don't full understand a problem until I've finished writing the code and gotten it running. Then in the course of debugging it I will often discover new things.
A year later I may try to refactor and rewrite the code, and it will come out better again.
And a year after that once more. Usually by the third rewrite there is nothing left to trim and no more performance to squeeze out.
And a few years after that when the code has been used in several projects and never had a problem or needed any rewriting and I've never looked at it and said "why did i do that?" then I know it's fully mature.
dragonfax · 2 points · Posted at 21:57:09 on April 26, 2018 · (Permalink)
I rewrite code because I always find that I've learned so much since I originally wrote it.
GISftw · 2 points · Posted at 22:12:41 on April 26, 2018 · (Permalink)
I think what Joel is saying means "at a large scale". Of course it is almost always a bad idea to redo an entire functioning product code base all at once. It is not always a bad idea to redo small pieces over time as requirements change. Eventually you might replace the whole code base, but the entire time you would have maintained a functional product.
Of course, I say "redo" not "throw away"... you have to read the previous code (and probably some of its previous revisions) to gain the historical knowledge of why it exists in its current form. Joel mentions many esoteric bug fixes over time that add up to ugly code, but if those are properly commented/documented, then you won't lose them when you redo the code.
That being said, there are a lot of bad programmers out there and thus a lot of bad code. This especially holds true in the modern web scale world where speed to market often takes precedence over proper architecture. There is a reason your website requires 10x more server resources than you thought it would...
jaehoony · 2 points · Posted at 22:47:42 on April 26, 2018 · (Permalink)
Outdated article filled with holes from 18 years ago. Why is it posted for the n-th time and why are you people amazed by this?
SpartanVFL · 2 points · Posted at 22:57:18 on April 26, 2018 · (Permalink)
Or you’re junior level and the old code actually is a mess
ravinglunatic · 2 points · Posted at 23:27:46 on April 26, 2018 · (Permalink)
My client would love nothing more than to just stamp the words “upgraded to mvc” on an old webforms project. I wish we could...
CantaloupeCamper · 2 points · Posted at 00:18:25 on April 27, 2018 · (Permalink)
Hell I want to rewrite my own code....
the_rabid_beaver · 2 points · Posted at 00:19:04 on April 27, 2018 · (Permalink)
If you've ever seen code written by a bunch of H1B contractors, you wouldn't agree with this statement.
spockspeare · 2 points · Posted at 00:54:06 on April 27, 2018 · (Permalink)
It's actually the opposite, if it's code you wrote recently.
They want to rip it up because 99% of projects start with an incomplete understanding of what the real requirements are.
Check that. it's 100%.
And by the time you're half done, you realize you should be coming at it from an entirely different direction because you finally grok what the requirements should have been all along.
rotharius · 2 points · Posted at 02:03:59 on April 27, 2018 · (Permalink)
This post is from 2000 but I think it might be pretty prophetic: most code I see is intentless, ugly throwaway code. As if we, as a profession, as a culture, do not embrace best practices and have to reinvent the wheel again and again...
Reddit1990 · 2 points · Posted at 02:52:39 on April 27, 2018 · (Permalink)
Ive never had that throw away code mentality, for whatever reason. Its probably harmed me in some ways, because I will always try to modify code as little as possible even when it might make sense to add a new system instead of cluttering an old one. Learning to balance when to write new code vs using old systems can be tricky.
bladelock · 2 points · Posted at 04:06:15 on April 27, 2018 · (Permalink)
TIL there's a law that states reading code is harder than writing it. I thought i was the only one who has more difficulty in reading code all this time. Wiser today now
phillijw · 2 points · Posted at 04:19:19 on April 27, 2018 · (Permalink)
Most programmers don't put much effort into writing readable code. If they did, the code would probably be better to begin with.
ummaycoc · 2 points · Posted at 04:20:37 on April 27, 2018 · (Permalink)
Just responding to the headline as I didn't read the article (this is an internet comment, after all), but that is completely ass backwards. Reading is easy, writing is a skill that takes work to develop. Children can read, and relatively young people can read well–very few people can write well.
There's no prize for reading, yet there are many for writing, and programming isn't somehow magically different than the other communicative endeavors of humanity.
You want better code? Give people more time and a better and more extensive editorial feedback loop on their writing. Harper Lee had an editor; you're not better than Harper Lee.
lavaeater · 1 points · Posted at 06:56:17 on April 27, 2018 · (Permalink)
Bla bla, read the article, if it's so fucking easy reading, why did you write something instead of reading something and understand it? Huh?
Answer that, genius!
And have a good day, sir.
ummaycoc · 1 points · Posted at 12:25:58 on April 27, 2018 · (Permalink)
:-)
shaggorama · 2 points · Posted at 04:44:57 on April 27, 2018 · (Permalink)
I don't think that's it at all. Old code bases accumulate technical debt. When confronted with this, a new person on a project often immediately sees this stuff and is like "why the hell are they doing it that way?"
lavaeater · 2 points · Posted at 06:55:02 on April 27, 2018 · (Permalink)
Of course - but the problem is the myth of the "complete rewrite". Huge costs to get the same thing but prettier code? Paying twice for the same thing?
Read the book "working with legacy code".
Encapsulate,write tests, refactor.
oliviacode · 1 points · Posted at 07:40:40 on April 27, 2018 · (Permalink)
lavaeater gets it
book link for the lazy: https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052
lavaeater · 0 points · Posted at 08:46:50 on April 27, 2018 · (Permalink)
Thanks, I think the poster I commented on also gets it, thanks for linking the book!
shaggorama · 1 points · Posted at 08:30:03 on April 27, 2018 · (Permalink)
I never suggested "The Complete Rewrite" was a good idea, I was just saying it's dismissive and conceited to suggest that new members of a project who think legacy code is ugly and would like to rewrite it given the opportunity are wrong, and that instead it's good code but they're just too lazy to read it properly.
lavaeater · 1 points · Posted at 08:46:13 on April 27, 2018 · (Permalink)
Sorry, I didn't mean to imply that you suggested that, I meant that yes, you're right, the problem is often that folks jump to the wrong conclusion regarding the best solution to that problem.
The code might very well be shit - but it's a polished, experienced turd. The solution to the unreadability is not to throw it away, but to slog through it and refactor and test it. While doing that one will surely learn a lot.
But sometimes even that won't work... what do you do then?
shaggorama · 1 points · Posted at 08:58:12 on April 27, 2018 · (Permalink)
It depends on what you mean by "work." It's not clear what the root problem is. If all we're trying to solve for is elegance, some times you need to bite the bullet and accept that occasionally "if it ain't broke, don't fix it" is appropeiate. If maintenance is becoming a problem, do your best to isolate components and replace it btick-by-brick (on your maintenance schedule) with a more versatile/modular solution.
lavaeater · 1 points · Posted at 10:16:18 on April 27, 2018 · (Permalink)
Yes yes and yes.
Many many, me too, developers, think there are silver bullets and easy solutions out there, but one has to really consider the options!
mgkimsal · 1 points · Posted at 11:51:39 on April 27, 2018 · (Permalink)
I wrote a longer post somewhere else, but the big assumption here is that this codebase, however ugly or difficult, actually does work as people are wanting it to. When that's the case, yes, but the bullet and deal with ugly/difficult/inelegant code.
I've come in to tech projects where, once you dig in, it's found out that much of X isn't actually working as expected, but users are just working around the bugs (laura just ignores the daily report button and compiles her own every day because the report button takes 3 hours and the data is wrong 80% of the time). Depending on the severity of these issues, that may or may not justify the "complete" (or mostly complete) rewrite, but... the assumptions in the "never rewrite!" are that the code/systems work, and are just ugly/difficult.
lavaeater · 1 points · Posted at 07:51:56 on April 28, 2018 · (Permalink)
Of course, there are never easy solutions or answers - never rewrite is obviously wrong when what you're dealing with is not actually working.
I actually have that issue right now - we have a component in the software we're working with, sort of like a modular scripting tool - user can drag and drop modules that take input, does stuff with input, has output. Sounds at least somewhat straight forward.
The code is fucking backwards. The architecture is just... wrong? Modules are not standardized, they do not have formalized inputs or outputs, like there is no IModule interface, the structure is not a straight list for some reason but a weird tree which just makes stuff more complicated than necessary (you will never ever have a cloud of stuff in this thing) and all the modules do their thing in different ways... so everything is broken, code-wise.
And the only customer basically only works with this thing and there are bugs in literally every module - so, do we fix all the bugs in this mess or write a new thing?
I say write a new thing and reuse algorithms. Perhaps some automated tests in there?
But the software is much larger than that one component, so it would be silly to rewrite the entire application - we just need to figure out a cleaner architecture for this one thing and fix it so we can add features and fix bugs without going insane.
If you have ever seen untestable code, this is it. Dependency injection is complicated - so every dependency is a singleton. WHAAT?!
A property might load a file when accessed.
Every class just randomly instantiates database connections.
It is a hot mess. But the ideas are sound, we just need to rewrite that fucking mess.
mgkimsal · 1 points · Posted at 12:15:00 on April 28, 2018 · (Permalink)
There's another aspect I'm not sure I explicitly put in before, but was on my mind - security. If something is so "messed up" that no one can understand it, and have trouble even keeping up with bugs... it's probably going to have unknown security issues. Just rebuilding with a known set of good libraries or framework will force you in to some patterns which will avoid common security errors.
WOW....
Had a system years ago which did a lot during a constructor - like... include multiple other files, did about 15 DB queries, logged info, and might send an email under certain situations. I asked to modify that to an 'init' or 'setup' method, so that I could reuse the class, and... no one understood why.
It's experiences like this where the Joel stuff really needs some asterisk on it, explaining the assumption that the rest of the team is competent. Yeah, I know this sounds harsh, and... I've been the incompetent person on a team a couple times early on in my career (sorry previous colleagues!). But the assumptions may lead people to make suboptimal decisions...
Not a security issue so much but was just dealing with some small web app which I'm trying to add a bit of functionality too. Had this been done with some normal framework, (this is a PHP app), adding my new stuff and making the mods would have taken around an hour. It's taken about 4 hours so far, and I'm not done. Everything is global. File X loads something else which parses some vars and sets a bunch of required vars - great, I can reuse that in what I need. Nope - it also sends emails whenever it's loaded. Yeah, it saved the original people some time to 'slap' this together, but... it's now multiple times more complex to touch - and... it still needs to have every query rewritten because they're all open to SQL injection. This is another example of rebuilding with good tools would probably have taken just a long as the 'small upgrade', and I'd feel much better about the fundamental foundations, instead of reactionary patching what I happen to spot. Perhaps this is what we should mean by 'reactive' programming? :)
lavaeater · 1 points · Posted at 18:45:25 on April 28, 2018 · (Permalink)
Jesus... your story reminds me of a classic asp site I got my hands on once... it was made by one of the employee's sons during a summer break or something.
It was all sorts of strange. It had include files. Like all pages included include.asp. Which included 10 more files. All of those included like any number of files... aaah...
Digletto · 2 points · Posted at 05:24:09 on April 27, 2018 · (Permalink)
At the same time a lot of (actually) old code is a mess. Like 90s and back.
oliviacode · 2 points · Posted at 07:38:39 on April 27, 2018 · (Permalink)
The secret is your new code is also a mess. But its your mess so tolerable (to you).
Digletto · 1 points · Posted at 09:45:35 on April 28, 2018 · (Permalink)
And you know, it's written 30 years ago when there was less knowledge on how to structure and work with large code projects and just worse languages etc. Code can be outdated even without bias you know.
oserna · 2 points · Posted at 05:40:18 on April 27, 2018 · (Permalink)
I couldn't even read the whole article.
STylerMLmusic · 2 points · Posted at 06:01:57 on April 27, 2018 · (Permalink)
I couldn't possibly be more of an amateur at programming but I'm really enjoying reading these comments. I'm learning a lot.
oliviacode · 1 points · Posted at 07:37:13 on April 27, 2018 · (Permalink)
Great attitude - keep that same learning mentality when you become an expert too. :)
FriendlyKush · 2 points · Posted at 06:15:12 on April 27, 2018 · (Permalink)
This brings me closure.
tolland · 2 points · Posted at 06:43:09 on April 27, 2018 · (Permalink)
In the last 20 years (like the 20 years before that) the quality of software, and the performance of programmers has increased massively. It's largely analogous to the performance improvements of athletes and other specialist activities like chess. The world has moved on, and it leaves old coding styles and techniques behind.
A large part of my previous job was working with code bases of that vintage, i.e. late 90s and early 2000s for retail POS and backend systems. And f**k me was that a PITA.
In the next 20 years, the majority of our current code base will be re-written. It's inevitable.
The question is not, if it should be re-written, but when
gamebuster · 2 points · Posted at 06:57:08 on April 27, 2018 · (Permalink)
I write code in small tested throw-away modules designed to be able to be deleted and recreated easily at any time.
nydstyrk · 2 points · Posted at 11:27:51 on April 27, 2018 · (Permalink)
If so please tell me, Joel, why didn't you keep on refactoring FogBugz but instead threw it all away and started writing Trello?
frisch85 · 2 points · Posted at 11:39:51 on April 27, 2018 · (Permalink)
I'm not sure mate, if I inspect code from my early days and now realize I could achieve the same thing with 1/4th the code maybe my old code is actually a mess...
m4xc4v413r4 · 2 points · Posted at 12:32:56 on April 27, 2018 · (Permalink)
I don't really agree with the statement.
Most of the time when I rewrite projects, mostly personal ones, it's because i evolved over time, I know how to make it better and more efficient.
forvotes · 2 points · Posted at 14:42:44 on April 27, 2018 · (Permalink)
ALWAYS REWRITE EVERYTHING! https://youtu.be/XcUUY8ziTuk
whozurdaddy · 2 points · Posted at 06:39:57 on April 28, 2018 · (Permalink)
part of the problem is a weak understanding of the architecture. Rather than fix the core problems, the code gets hacked to bits. In time its just a mess that barely works.
I liken it to adding something to a car. Youre not quite sure how to properly install a new stereo, so you just poke around until you can get 12 volts from ...anywhere. Then run wires to the sub in the backseat. no understanding of how the thing is supposed to work, and you probably have limited time to make it work...so ill just steal 12v from the cigarette lighter.
do that enough times, and your car just catches fire.
but sometimes the code IS a mess. Even veteran programmers just zero in on a quick fix to get the problem solved, which over time creates the very same problem.
izackp · 2 points · Posted at 13:53:58 on June 13, 2018 · (Permalink)
I'd rather refactor code then create it from scratch. In fact, I learn the most as a programmer by reading other people's code.
dreamingforward · 2 points · Posted at 18:50:57 on June 14, 2018 · (Permalink)
It's an incomplete truth. Most code is poorly architected, so there's no implicate order for the mind to latch onto. Well-architected code is a pleasure to read and obviously correct.
ngroot · 3 points · Posted at 14:49:20 on April 26, 2018 · (Permalink)
If the code is hard to read, someone didn't finish writing it.
yonreadsthis · 3 points · Posted at 15:23:57 on April 26, 2018 · (Permalink)
Well, that part is probably true. But, starting over, and over, and over, is like rehearsing a theatrical. Every time you rehearse, you get a better understanding of the whole project. Eventually, you come to the dress rehearsal, and then, performance! Unfortunately, business timetables tend to go straight from proposal to performance and, thus, to defeat quality.
we-all-haul · 2 points · Posted at 14:47:25 on April 26, 2018 · (Permalink)
It was hard to read your title, so I wrote my own: "It's harder to read code than write it, just throw it away"
pukatm · 2 points · Posted at 15:47:49 on April 26, 2018 · (Permalink)
Is this "fundamental law" real or just hype and marketing stuff?
It's a very bold statement to suggest that a programmer is wrong to think that old code is a mess and is almost insulting. Software requirements change all the time and quickly. Programmer turnover rate is high. When an old and well-designed solution keeps being patched over and over again to cater for new unforeseen requirements under pressure, when the new guy on the block is inheriting code of questionable quality, reading isn't hard or effortful, but it is painful: more reading is uncovering more ugly implications (the programmer ends up responsible for the code at the end of the day) and stopping to rewrite is an effort at putting the programmer at ease (the programmer is now in a different mindset in which they can accept responsibilities because the solution becomes theirs). Software engineering is difficult.
🎙️ the_phet · -1 points · Posted at 15:56:29 on April 26, 2018 · (Permalink)
The fundamental law is that it is harder to read code than to write it. And this is very true.
pukatm · 1 points · Posted at 16:02:21 on April 26, 2018 · (Permalink)
To clarify: better to perform some studies before going as far as saying these things are a "law"... This isn't very true just because you say so... I hope!
Krakob · 2 points · Posted at 18:42:59 on April 26, 2018 · (Permalink)
I appreciate that the headline gets straight to the point because let's be real, no one here actually read the article 😝
Mulan-McNugget-Sauce · 2 points · Posted at 19:28:14 on April 26, 2018 · (Permalink)
looks back at old code Fuck I don’t even know what the hell this is erases and rewrites looks the exact same as old code Shit.
the_evergrowing_fool · 1 points · Posted at 14:18:19 on April 26, 2018 · (Permalink)
Noted, but there is also the valid reason to chance old code because it needs to be integrated with new one.
Yserbius · 1 points · Posted at 14:38:38 on April 26, 2018 · (Permalink)
I am currently tasked with fixing a series of Java bugs identified by a linter. One group involves potential null pointer issues where there is a method (written, according to the VC, around 10 years ago) that may catch an exception, log it, and return null. Many of the calling methods don't have null checks. There is no way that this code is not a mess and fixing it would be the better option.
I'm sure in many cases Joel would be correct, but in my experience old code is often a massive unmanageable mess of items built on top of other items and hard-coded hacks put in due to time and budget constraints.
elebrin · 1 points · Posted at 14:49:52 on April 26, 2018 · (Permalink)
If you have code that you don't understand and no unit tests, write the unit tests. If you do have unit tests, read those instead. One of my rules of unit testing is to always go for readability first with very clear structure.
icetheace · 1 points · Posted at 15:16:44 on April 26, 2018 · (Permalink)
A big part of it is the human factor. People get into programming thinking it's just stuff they write, or at least that's the initial draw. Then when you realize your cto only cares about clients and your second in command only care about old ways of doing things, and bad code gets splattered everywhere. You begin to regret it and it never gets fixed cause well there are sprints. Which is just great for logical data driven design because well productivity is 1# always. Then as you work up you realize the real garbage and the humanity of lifers. It turns into one big incest fest of awful mess of making things productive. Then comes the newly hired terminator because features are taking too long....yay!
MasterLJ · 1 points · Posted at 15:27:56 on April 26, 2018 · (Permalink)
I've found it to be a spectrum [reads code well]-----------------------[writes code well]. I am definitely in the camp that I can code better than I can read it. I would also concede that it's probably not normally distributed, as the author suggests.
That said, I fundamentally believe in throwing out code often, and taking a prototypical approach mostly because we kid ourselves in trying to waterfall the requirements of a project. You can develop much better solutions once you've eaten the dog food, designed the system, seen the similarities, seen the performance issues, seen the security issues, etc etc etc.
For me it's more about hubris, in that we think we can ever really properly account for all the use cases without getting our hands dirty.
It also goes into testing. There's a lot of hubris there as well. On the day you start working on a feature, you write your tests, your tests are now hard-coupled to the exact same set of use cases that your working code expresses. But what is a very common type of bug? A missing use case! How do you test for that with certainty? You can't test what you don't know. In the same vein, you can't design a system for things you don't know, even when you have the best design team possible, and are free of "we need to get this into the project by Friday" type asshattery.
The tl;dr is that the best code blends the old and the new. Carry forward healthy pieces of code, along with their battle hardened tests, but re-design things that are square pegs trying to fit in the round hole of the real context surrounding the project. All the while keeping in mind the extraordinarily high value of running, working code. It's about balance, more than extremes.
[deleted] · 1 points · Posted at 15:29:38 on April 26, 2018 · (Permalink)
or we just grow our skills and old code IS terrible
LetsGoHawks · 1 points · Posted at 17:30:27 on April 26, 2018 · (Permalink)
Code is very rarely "great" or "terrible". It usually resides somewhere between the two.
ThatInternetGuy · 1 points · Posted at 15:32:10 on April 26, 2018 · (Permalink)
When it comes to my code, the old code can't be reused because it worked well for the technologies back then. More often than not, the code was to integrate with particular version of frameworks (be it database, web service, cryptographic or else) that were acceptable for that time. To give a quick example, my old code used MD5 to hash and LINQ-to-SQL to access the database and it used WCF to call web APIs. It's unimaginable that any of that code is reusable, because it's deeply connected to obsolete or insecure technologies.
Another main reason to abandon old code is that we keep learning new techniques and old code didn't not take advantages of these new knowledge that we've learned. Take 2FA and QR code, for example, before knowing it, my application would send an email to verify a secure login, but now user just scans a QR code to setup 2FA for the first time and then use Google Authenticator on their phone to generate a 2FA code to verify their identity.
Last but not least, the old implementation is just wrong. There were times when I never heard of HMAC needed to verify decrypted data and I coded the encryption based on that assumption. Turns out... without HMAC, the encrypted data can never be verified later that it's not tampered with.
[deleted] · 1 points · Posted at 15:33:31 on April 26, 2018 · (Permalink)
Someone said programming is theory building. Humans are not very good at building formal theories and communicating those theories to others. I have yet to work on a codebase where intent, code, and documentation all align. Everything is always out of sync and a non-trivial portion of the bugs come from that misalignment.
redcodefinal · 1 points · Posted at 15:36:27 on April 26, 2018 · (Permalink)
I don't think this, my problem is more that a massive rewrite is sometimes more effective when you've programmed yourself into a corner.
etrnloptimist · 1 points · Posted at 15:44:44 on April 26, 2018 · (Permalink)
I love Joel. And as usual for him, this is solid, traditional advice that I thoroughly agree with.
However, the era of modern programming may turn this traditional advice on its head.
We now live in the era where we have access to a vast number of open source, commercial friendly (BSD/MIT), extremely high quality purpose built libraries we can now take advantage of.
A large portion of old codebases are poorly thought out, hastily built, and bug ridden modules designed to do certain things. Caching libraries, event systems, pub/sub architectures. Custom IPC. Oh so much IPC.
When you look back at all these subsystems, nearly all of them can be replaced with highly performant, mature, open source libraries, packages, and services.
There is simply no reason nor justification for continuing to use and maintain all this old code that, turned upside down, looks like you are trying to reinvent the wheel, only very poorly.
grauenwolf · 1 points · Posted at 19:04:04 on April 26, 2018 · (Permalink)
So what? He explicitly said you can replace parts of the application.
etrnloptimist · 1 points · Posted at 19:17:09 on April 26, 2018 · (Permalink)
Because 90% of most applications are undifferentiated heavy lifting: things every large application needs to do, but isn't the business function of your specific application.
Open source has changed the nature of this by abstracting away nearly all of that.
If you are to swap out 90% of your application and save the 10% that is actually your unique competitive advantage, you are basically "throwing away your application" and starting over.
grauenwolf · 1 points · Posted at 19:31:16 on April 26, 2018 · (Permalink)
What's the term for the logical fallacy where you change the definition of a term in order to alter the original meaning of an argument?
etrnloptimist · 1 points · Posted at 19:39:36 on April 26, 2018 · (Permalink)
Strawman. Did I do that?
Ganoash · 1 points · Posted at 15:48:00 on April 26, 2018 · (Permalink)
Heh.
edapa · 1 points · Posted at 15:51:35 on April 26, 2018 · (Permalink)
I think a total rewrite of a large system is almost never a good idea, but if you are in a place where you are scared to rewrite individual modules or features it means you have a serious testing problem.
squishles · 1 points · Posted at 15:52:08 on April 26, 2018 · (Permalink)
It's harder to write code that's easy for others to read. The earlier version was likely written under the gun on a short deadline to get a feature/product/system out, making it very likly they took readability short cuts, among many many other shortcuts.
It is still easier to fix the busted terrible code base than truly write from scratch, but that doesn't magically mean the busted version is good.
Warspit3 · 1 points · Posted at 15:52:49 on April 26, 2018 · (Permalink)
I had a class in University where on the programming part of the exam our professor would provide libraries that we needed to use/modify to do the specific tasks needed. The class was based on C++ and holy fuck me was it stressful to read and alter his libraries in half an hour, not to mention use them in conjunction with my own functions that he required we add.
deadlyicon · 1 points · Posted at 15:56:16 on April 26, 2018 · (Permalink)
Well written code is easy to read. If your code is hard to understand by a skilled programmer then it’s subpar and should be refactored.
Code is a liability and should be reduced in complexity as much as possible if you want to continue being able to evolve your codebase.
mrcrassic · 1 points · Posted at 15:59:32 on April 26, 2018 · (Permalink)
Okay, so let's say you're given a codebase that is unreadable, barely passes tests, is lacking test coverage in a ton of places (i.e. bugs on the horizon) and was mostly maintained by one person that left the company some time ago.
You want to make the codebase cleaner, introduce more tests, etc.
Doing so will essentially force you to dump most of the codebase.
But this heap of shit is making the company $10M/month.
What do?
eskimoFry · 1 points · Posted at 16:03:07 on April 26, 2018 · (Permalink)
I think "thowing out code" needs to be differentiated from a rewrite.. and the difference could be that the high level to middle level design is changed when altering the code. In that case, it is a "throw away". Otherwise, it is just maintenance.
mrcrassic · 1 points · Posted at 16:50:20 on April 26, 2018 · (Permalink)
Right, and I'm not sure that this difference is made clearly here.
Moving the code around and making it cleaner without affecting the core of how it works == maintenance (lower risk, generally speaking)
Doing the above and changing core functionality == rewrite (high risk made lower through keeping higher level tests mostly intact)
Armchair a16z alert: After the first buy out, Netscape essentially created a new browser, meaning new everything, despite the fact that Netscape 4.x was mostly loved by its customers. This is super risky.
LetsGoHawks · 1 points · Posted at 18:03:31 on April 26, 2018 · (Permalink)
So, you're saying it passes the tests?
Seriously though... you fix it one step at a time. BECAUSE IT ALREADY WORKS. And if you think you can rewrite it and deploy a Version 1 that the customers think works as well as the old one, you're wrong. It's much better to spend all that time and energy improving the old one. Not only will the customers get happier as the product they already know how to use gets steadily better, they won't get all pissed off while your crappy Version 1 iterates it's way to being as good as the old product was.
mrcrassic · 1 points · Posted at 18:18:34 on April 26, 2018 · (Permalink)
That's a slippery slope that leads to shit never getting fixed, though.
LetsGoHawks · 1 points · Posted at 18:32:43 on April 26, 2018 · (Permalink)
So when I said "fix it one step at a time", you read it as "don't fix shit".
Interesting.
nil_von_9wo · 1 points · Posted at 16:07:06 on April 26, 2018 · (Permalink)
While it is true that it is always harder to read code than to write it, even for the authors, how painful it will be to read varies.
I've worked on projects where developers actually don't make a complete mess.
And they I've worked on projects where developers seemed to feel that if nobody else could read their code, they'd have a job for life.
Unfortunately, nobody ever taught clean code when I went to school. Nor has it ever been demonstrated in any tutorials I've ever read trying to teach programmers a new language.
So, I can only imagine the typical developer has no clue what that really means and most code in the wild should be burned with fire.
SonOfWeb · 1 points · Posted at 16:11:29 on April 26, 2018 · (Permalink)
I remember my first serious job - fixing bugs in a large system. Whenever we fixed bugs we would add unit tests to make sure the bug was fixed, but often times the unit tests felt like documentation of however the system happened to actually work, not how the system was supposed to work. Most of them would use mocks to say "make sure this method calls this other method and this third method." aka "make sure the implementation is the implementation." That's what bothers me about legacy code: the specification is "it should work the way it's been working" without careful evaluation of whether the way it's been working is the right way. Any code that's not actively throwing exceptions or showing noticeably wrong behavior right away is assumed to be correct.
chompsky · 2 points · Posted at 16:14:38 on April 26, 2018 · (Permalink)
Working with legacy systems inevitably leads me to the category of bug where I'm not asking "why won't this work?" But rather "how on Earth did this ever work in the first place?" Multiple fixes over the years to keep it working the same, not working correctly.
wuphonsreach · 2 points · Posted at 06:38:27 on April 27, 2018 · (Permalink)
Agreed. That's a classic testing mistake. Tests should focus on behavior, not implementation. If I'm writing a test for
translate object A into object B, I don't care how you implement that as long as it results in the correct value coming out the other end.It's one of my dislikes of the C# Moq library examples, that they show setup of tests that verify if a method is called from inside the SUT. Fortunately, you don't have to follow that pattern to have Moq be useful.
e-couch · 1 points · Posted at 16:14:19 on April 26, 2018 · (Permalink)
I've tossed an entire code base before and started from scratch. As an architect it's sometimes easy to see fundamental flaws in the design post mortem, and sometimes it has to do with the technology that was used or the base approach to a problem. One example I can think of was a system that was "90% done" according to the manager. I took a look at it and realized that the entire system could be replace with a scheduled sql job. No need to build a scheduling system that runs a .net app that iterates through rows in a database when a single query that will run faster and be scheduled with a reliable job management system that we know works. Also, a majority of the code was shit.
What's to say when you actually make an honest assessment of a body of work and realize that it's just bad? Sometimes you can't polish a turd.
SocketRience · 1 points · Posted at 16:15:32 on April 26, 2018 · (Permalink)
I'm NOT a programmer
but i'm learning a tiny bit through googles new "Grasshopper" app..
learning by reading some code and then changing or adding stuff to it
dasignint · 1 points · Posted at 16:16:28 on April 26, 2018 · (Permalink)
This was always the point I most disagreed with him about. I can't believe that every large codebase is of roughly the same quality, and the apparent differences are that subjective. Why would that be true? Maybe he just hadn't seen true spaghetti in production? I assert that I have seen true spaghetti in production, and that it caused serious problems over long periods of time, because of how it was written, not because of how we read it.
bitparity · 1 points · Posted at 16:25:04 on April 26, 2018 · (Permalink)
I'd be interested in anyone in this forum who is simultaneously a programmer but also someone who writes academic articles, and or creative fiction.
Because I find in writing essays, it is always better to completely rewrite than to adapt existing writing, because the overall logic to the argumentation can be reflowed more cleanly, even if you forget the details. However, in english writing and argumentation, the inverse is true to that stated mantra "it's harder to read code than it is to write it." Clearly in english writing, it's easier to read an argument than to write it.
donny138 · 1 points · Posted at 16:32:32 on April 26, 2018 · (Permalink)
I do this with my code, and just about every other project that I come back to after a while.
Epic_Mine · 1 points · Posted at 16:38:32 on April 26, 2018 · (Permalink)
I do this all the time with buggy arduino sketches
ekchew · 1 points · Posted at 16:40:23 on April 26, 2018 · (Permalink)
This is kind of what I picture in my head:
So yes, overall reusing should save time. But it's how it's spent man!
UpperMine · 1 points · Posted at 16:59:17 on April 26, 2018 · (Permalink)
I disagree. For me, it’s extremely easy to read code. But don’t ask me to write it cause I have no idea what I’m doing.
crusoe · 1 points · Posted at 17:02:24 on April 26, 2018 · (Permalink)
Somewhat true.
But after a while with enough experience, you can look at code and go "It looks good but I need to understand it" vs "What the fuck were they doing?"
muldoons_hat · 1 points · Posted at 17:08:20 on April 26, 2018 · (Permalink)
It’s like when someone types a wrong character in their password and they just delete it and start over.
earthboundkid · 1 points · Posted at 17:09:03 on April 26, 2018 · (Permalink)
I keep meaning to write a thorough refutation of this article. If nothing else, let me say his examples have aged poorly and now show the opposite of what he thought. I don’t think anyone wants to emulate IE6 anymore.
JGailor · 1 points · Posted at 17:10:05 on April 26, 2018 · (Permalink)
I find I’m ok reading code that adheres to the Single Responsibility Principle. It’s just that most code tried to do ten things and you start having to hold a lot in your head at once to understand a single function.
colly_wolly · 1 points · Posted at 17:19:30 on April 26, 2018 · (Permalink)
For me its usually the opposite, a shot load of code that could be done in a couple of lines. Its often accompanies by a bit of database redesign, which I am not afraid of any more.
mirelinha · 1 points · Posted at 17:12:14 on April 26, 2018 · (Permalink)
Absolutely not. I never throw away a code for I am a piece of shit who is great at using parts of other codes to make mine. I'm a horrible person but good at reading.
bumbuff · 1 points · Posted at 17:19:32 on April 26, 2018 · (Permalink)
I am only a casual programmer, but I learned to add keyword notes so I can just ctrl+f things I know I use frequently and may want to refer back to.
cemremengu · 1 points · Posted at 17:19:34 on April 26, 2018 · (Permalink)
We have a 10 year old ASP WebForms system and I can assure you that it's not only hard to read but also hard to write. People are even scared to delete comments.
ryjen78 · 1 points · Posted at 17:19:36 on April 26, 2018 · (Permalink)
perhaps a crap jar.... put 25 cents in every time you think its crap. If you get enough to support a internal rewrite. knock your socks off.
bonly · 1 points · Posted at 17:22:26 on April 26, 2018 · (Permalink)
Just because code is functional doesn't mean it isn't a mess...if you don't write it to be readable AND functional you're going to have a bad time.
[deleted] · 1 points · Posted at 17:26:24 on April 26, 2018 · (Permalink)
I like saving up code so I always have something for a rainy occasion.
[deleted] · 1 points · Posted at 17:28:44 on April 26, 2018 · (Permalink)
Doesn't that imply that you SHOULD throw away old code?
Polengoldur · 1 points · Posted at 17:40:03 on April 26, 2018 · (Permalink)
i mean. it'd help if there were comments. not even a lot. just fucking something.
fun facts: that old pinball game that came standard in the older Windows versions? they couldn't port it over because it was too buggy in windows 10, and there wasn't a single comment in the things coding so they had no idea how it worked.
want nice things? take the time to add comments.
mt3hackman · 1 points · Posted at 17:51:04 on April 26, 2018 · (Permalink)
Most of the time we go back and update old code essentially reading and writing it
m_krm · 1 points · Posted at 17:54:25 on April 26, 2018 · (Permalink)
Or there skills today are better then they were yesterday. And there knowledge of whatever language, framework or toolkit is more then what it was when that was wrote. Besides, it's more fun to build new stuff rather then to maintain someone elses legacy. 😀
zarlss43 · 1 points · Posted at 17:56:11 on April 26, 2018 · (Permalink)
My boss always wants to throw away my working code because he thinks its a mess :(
MAreddituser · 1 points · Posted at 18:02:41 on April 26, 2018 · (Permalink)
Coding is as distinct to each person as our handwriting. Worked with brilliant coders and each one had problems reading the others.
l_hutz · 1 points · Posted at 18:06:34 on April 26, 2018 · (Permalink)
In my humble opinion;
The first rule of software engineering - there are no rules. The second rule of software engineering - there are no rules. The third rule of software engineering - there are still no rules apart from these three rules.
Also rule four: horses for courses. Some engineers like rewriting and refactoring. Some are good at working with what’s already there. I.e. See the first three rules again.
ferociousturtle · 1 points · Posted at 18:11:36 on April 26, 2018 · (Permalink)
This advice bothers me for a couple of reasons, which I wrote up here[1]. First, I've participated in successful rewrites, and still think those were a good idea. Second and more importantly, most of the big tech companies we know and love (or hate) got their start by rewriting existing products. Google was a from-scratch rewrite of older search solutions. Facebook was a from-scratch rewrite of older social platforms. Etc. Just because it's a different team / company doing the rewrite doesn't mean it's not a rewrite.
[1] https://medium.com/@chrisdaviesgeek/rewrites-arent-always-a-bad-idea-f7439d3b27aa
JoaoCantor · 1 points · Posted at 18:15:57 on April 26, 2018 · (Permalink)
I hate reading other people's code so much.
fedekun · 1 points · Posted at 18:19:05 on April 26, 2018 · (Permalink)
I don't think so. Like learning to draw, your old drawings always look shitty, until they don't.
yesman_85 · 1 points · Posted at 18:23:58 on April 26, 2018 · (Permalink)
I don't think this is just for programmers and code. If I build a project of wood it's always more fun to make something new than to fix up the old.
Working on new stuff is always more fun.
skulgnome · 1 points · Posted at 18:24:09 on April 26, 2018 · (Permalink)
This is because most programmers spend far more time writing source code than reading it.
AKA_Wildcard · 1 points · Posted at 18:24:51 on April 26, 2018 · (Permalink)
Especially when it's anyone else's code but yours, or you were really really drunk during that period of your life.
dem_c · 1 points · Posted at 18:26:45 on April 26, 2018 · (Permalink)
When I find a new and better way to programm some thing, I end up writing the whole thing from scratch as implementing it to original cade would just make it more terrible
G3netic · 1 points · Posted at 18:27:12 on April 26, 2018 · (Permalink)
I, 100% of the time, look at a 'completed' program and just feel like there is a better way to do it.
That being said I find that often by writing the code on the fly and getting it into a working state, using that word losely here, I discover how the code should actually be designed, atleast in the parameters of my ability. After a little over a decade of programming, about half as a professional, I am still never really satisfied with my code.
ARBEIT_MACHT_REEEEEE · 1 points · Posted at 18:28:36 on April 26, 2018 · (Permalink)
Excuse my ignorance, i'm not versed in any programming languages but wouldn't it be easier to read with a demarcation explaining what given sections do?, i'm asks ming notations exist but also that they are probably fucking annoying, and lead to formatting errors. So wouldn't it make since to just highlight a section of code in certain colors as you write it, having an application to take care of this might be complicated at first but if it doesn't already exist i'm sure this would make reading code much easier especially if an etiquette surrounding highlighting developed.
wuphonsreach · 1 points · Posted at 06:43:53 on April 27, 2018 · (Permalink)
In languages with methods/functions, you should be pushing those sections down into separate methods with descriptive names. Then it gets easier to understand the flow (less lines to look at) compared to getting lost in the details of how the flow is implemented.
Modern IDEs also have block outlining where you can hide the interior of the block between braces / brackets. That helps a bit too.
vvvvalvalval · 1 points · Posted at 18:51:35 on April 26, 2018 · (Permalink)
Counter example: how Room Key migrated from PHP to Clojure and AWS http://www.colinsteele.org/post/23103789647/against-the-grain-aws-clojure-startup
the_red_scimitar · 1 points · Posted at 18:51:59 on April 26, 2018 · (Permalink)
It's not fundamental, so much as a lack of training and/or discipline. See Donald Knuth's "literate programming". It's possible to adapt much of it to typical coding environments.
cs117x · 1 points · Posted at 18:52:53 on April 26, 2018 · (Permalink)
More like a combination of lazy perfectionists
PM_me_UR_duckfacepix · 1 points · Posted at 19:02:26 on April 26, 2018 · (Permalink)
This is true, EXCEPT for anything coded by Theo's band of brothers.
Because those guys actually read all the code, repeatedly.
siderinc · 1 points · Posted at 19:03:17 on April 26, 2018 · (Permalink)
Reading code is easy, writing it is hard.. At least for me it is. What am I doing wrong?
mastaberg · 1 points · Posted at 19:04:41 on April 26, 2018 · (Permalink)
I don't really have a problem reading old code I wrote, I have had issues with reading others. But yea I guess redoing something your way can be easier at times, but I feel like this doesn't apply to boiler plate code.
YogiBoar · 1 points · Posted at 19:06:00 on April 26, 2018 · (Permalink)
Step 1 : look at old code, declare outdated/unreadable and explain to collegues how you can make it better. Step 2: scrap old code Step 3 : while coding realise the initial idea you had won't work. Step 4: struggle pointlessly to get a solution working within the sprint Step 5: end up with the same solution you scrapped.
russellbeattie · 1 points · Posted at 19:06:51 on April 26, 2018 · (Permalink)
Edge cases, bounds checking, error correction, workarounds and bug fixes: Things you never think about when rewriting code from scratch.
TheHappyPie · 1 points · Posted at 19:08:13 on April 26, 2018 · (Permalink)
maybe but I'd probably disagree.
you write something with a plan, the plan changes. requirements change. it's just a small change so nobody gives it much thought. 200 small changes later the code base is a mess.
Or, hey Xslt is really cool. let's go write everything in xslt. ah it's 12 years later and it's really hard to find developers to maintain this stuff because xslt is dead.
Or. you've got 20 coders working on different pieces of the pie. each team makes their own utility modules and does things a different way.
atomheartother · 1 points · Posted at 19:11:54 on April 26, 2018 · (Permalink)
There are good ways to rewrite a whole codebase if the code is really bad. You do it slowly, over time, replacing bits of code with other ones. You can't halt development for it, nor can you have a separate team doing the rewrite - the guys working on the codebase itself need to slowly update it.
scootscoot · 1 points · Posted at 19:22:00 on April 26, 2018 · (Permalink)
I can’t read this code, it was written in last years popular and now outdated framework, better rewrite it using today’s trendy framework.
[deleted] · 1 points · Posted at 19:25:52 on April 26, 2018 · (Permalink)
Did we really need an article on this?
theb1g · 1 points · Posted at 19:32:19 on April 26, 2018 · (Permalink)
Documentation is key
GetOffMyLawn_ · 1 points · Posted at 19:37:14 on April 26, 2018 · (Permalink)
It's hard to read because it's a mess.
I've seen a lot of terrible code. 10,000 lines of Pascal to do something you could do in 100 lines of Perl type mess.
Crazy__Eddie · 1 points · Posted at 19:39:42 on April 26, 2018 · (Permalink)
There's a difference between code that's difficult to understand, and code that's irretrievably broken. Very often the former leads into the latter as people rush to fix issues without understanding how shit works because it's too damn difficult to understand, but there's still worlds of difference.
Generally when you get to an irretrievable mess there are a lot more problems than just code. Lack of documentation, lack of feature specs, rigid micromanagement, lack of funding for QA, little to no standards for anything, technical leads that don't know what they are doing...when a project goes tits up it's more than poor coding...it's poor management. When it's that bad it doesn't often get fixed either.
the_void__ · 1 points · Posted at 19:41:12 on April 26, 2018 · (Permalink)
There can be many reasons for the "burn it down and start over" reaction. Some are legitimate reasons and some are not.
The thing is complex and difficult to understand and the developer isn't familiar with all of the nuances, as pointed out by the article.
The thing doesn't conform to company standards, making it more difficult to understand due to unfamiliarity.
The thing doesn't conform to the developer's design/pattern flavor of the week.
The thing was poorly designed or implemented to begin with.
The code may have been nice and clean to begin with, but has been subjected to numerous updates due to bug fixes and changing requirements over the years, and grew into a patchwork horror. Cleaning these up can be cathartic.
Hypersapien · 1 points · Posted at 19:50:15 on April 26, 2018 · (Permalink)
Isn't there a better way to represent code than a series of flat files in a directory tree, each with a sequential list of classes and functions?
Isn't there a way to create, access and edit these classes and functions that's more representative of the way they interact with each other?
L_darkside · 1 points · Posted at 19:54:40 on April 26, 2018 · (Permalink)
Once you have in mind what some code does, you re-think it with a different structure, thus feel the urge to rewrite it completely reorganized.
billbacon · 1 points · Posted at 19:57:54 on April 26, 2018 · (Permalink)
It usually happens when transferring from one programmer to another. The question is whether it's the new programmer OR the code that sucks. Often it's both and that's why it's so important to have qualified programmers in management.
firegodjr · 1 points · Posted at 20:04:36 on April 26, 2018 · (Permalink)
Bless you op <3
wtioverlord · 1 points · Posted at 20:05:18 on April 26, 2018 · (Permalink)
Sometimes the architecture is bad man
Furyswipes_VG · 1 points · Posted at 20:16:49 on April 26, 2018 · (Permalink)
This lua code works. But it is a mess. Should I rewrite from scratch?
emperorxyn · 1 points · Posted at 20:21:06 on April 26, 2018 · (Permalink)
Its not hard to read code its just a lot of effort and time consuming.
partbaddie · 1 points · Posted at 20:22:08 on April 26, 2018 · (Permalink)
If it is a project that is maintained and grown over time then the likelihood of the code actually being a mess is huge.
Feature creep is real and features added down the road tend to be done without consideration to making that feature accessible outside of the current desired scope. Alternatively it is also common for existing accessibility to be removed in favor of optimization.
The worst is when you have a client with an ancient application that was:
There are definitely times where rewriting is not only more beneficial down the road but may actually be faster than hacking in the new feature.
[deleted] · 1 points · Posted at 20:25:39 on April 26, 2018 · (Permalink)
Sometimes it's code where I didn't know the newer or better techniques available.
If working in new or fast changing languages better patterns / architectures emerge.
The key is to prevent as much repetitive code as possible. Use base classes/inheritance. Use helper classes and build util libraries. Any code that's not self evident what it does should have comments. That way refactors only have to hit one or a few places instead every code file.
I've never had issue refactoring my own code, other people's code however....
One of my college programming professors said something that pretty much as applied my entire programming career, changing code is always a much longer time consuming task than writing new code.
scrapmetal134 · 1 points · Posted at 20:27:23 on April 26, 2018 · (Permalink)
So we will be keeping that one file that somehow, through a black box of code, is compiled and run on demand in VB6. It contains over 2000 lines of code that lives in a handful of functions. And we customize this file on a per customer basis, mind you.
And we will be keeping the front end in VB6, where we are constrained by memory and addressing limitations. With it's terrible IDE and horrendous syntax. Not to mention how well it works with Windows 10 (Sarcasm)
And all those stored procedures written by a database dev that got fired too late into his cycle of work here? Are we keeping those too?
Fear of rewriting something is screwing this industry so hard. We are constantly aiming for progress, progress, progress and never anything stable and sustainable. Our work shouldn't be just about the customer, but about the developers who maintain it.
svayam--bhagavan · 1 points · Posted at 20:27:44 on April 26, 2018 · (Permalink)
So how to make reading code easier?
kevintaing86 · 1 points · Posted at 20:32:22 on April 26, 2018 · (Permalink)
Let me put it this way: If you had the opportunity to stay in 'merica with a lot of debt(and work to pay it off) or just move to another country and not have to pay debt?
oh_like_you_know · 1 points · Posted at 20:39:46 on April 26, 2018 · (Permalink)
This is completely true, but there are other factors involved as well that have nothing to do with how difficult it can be to understand someone else's code.
Codebases [at least active ones] are like a living thing - they are constantly changing to accommodate new features and functionality, new design patters, new libraries or modules, etc. So while the existing code very well may have been the best it could possibly be at the time it was written, adapting it to fit in with the rest of the codebase may be far more effort than just rewriting it.
This point is underscored if you ever go back and look at your own code - this somewhat lessens the argument that reading code is harder than writing it because you did in fact write it and should have some basic memory of how it works. And yet, even in this case, a rewrite is very often the preferred approach.
etheran123 · 1 points · Posted at 20:40:14 on April 26, 2018 · (Permalink)
It be like it is but it do-
TheAmazingGazza · 1 points · Posted at 20:58:49 on April 26, 2018 · (Permalink)
Also, comment your codes. You might understand it, but not the one who follow up your code a few year down the line.
henrycaul · 1 points · Posted at 21:00:26 on April 26, 2018 · (Permalink)
This article is a classic. Glad to see it resurface after all these years and get exposure to a new generation of programmers.
plasticrat · 1 points · Posted at 21:00:40 on April 26, 2018 · (Permalink)
Comments!
trigonomitron · 1 points · Posted at 21:03:25 on April 26, 2018 · (Permalink)
Wrong. My old code is always a mess because I'm always improving.
tias · 1 points · Posted at 21:10:51 on April 26, 2018 · (Permalink)
No. Believe me, it really is a mess.
Atomheartmother90 · 1 points · Posted at 21:13:06 on April 26, 2018 · (Permalink)
This isn't just programming. I feel this way about excel as well. My main job is building dashboard reports using Microsoft BI Suite and I am much better at building the reports than I am at going back and figuring out where I went wrong somewhere.
justinmchase · 1 points · Posted at 21:15:03 on April 26, 2018 · (Permalink)
Its worse than that, trying to build up all the context and background in your head takes a lot of time. Its easier to do targeted fixes but larger ones that require fundamental design changes are expensive and risky without a lot of context.
It can be easier to rewrite or layer and slowly consume the older code than to attempt to modify or maintain older code for this reason.
SlothHawkOfficial · 1 points · Posted at 21:15:21 on April 26, 2018 · (Permalink)
Holy crap, this is why I can never finish anything... I always get the feeling that the code is too unorganized and bad so I have to redo it..
Sephran · 1 points · Posted at 21:24:36 on April 26, 2018 · (Permalink)
At least where I work, everyone uses different languages, and they think their language is better. Usually the younger the programmer is, the more often they want to innovate and do new things.
When in reality, you probably don't need to touch the old code base and things are there for a reason. But no matter what it is, big or small, its always "easier" to rewrite it in a new language and completely throw out the old code.
I am all for moving to a new code base or look at redoing some crappy code, but I haven't found too much of it.
Is it ideal code? no. Is it really that awful though? NO!
I always laugh when I see some guy who has been programming for 2 years come in and make fun of code that was written by a guy with 25 years behind him. That 25 yr guy made mistakes sure, and the language used is a bit or completely outdated. But its written well, its functional.
Luna2442 · 1 points · Posted at 21:27:25 on April 26, 2018 · (Permalink)
Or! Because my timelines are crap so I accept the first thing that works lol
toomanydickpics · 1 points · Posted at 21:47:00 on April 26, 2018 · (Permalink)
This is true.. it's why I've given up so many times. If i can't just go straight through it's done for.
Fareley · 1 points · Posted at 21:48:10 on April 26, 2018 · (Permalink)
In my limited experience, code is a compromise between planning, time constraints and project management/constraints.
You start out cleanly, will a plan well thought out, for the given project constraint and attempt to satisfy that problem within the time constraints. Then the project constraint shifts, because the client changes their mind. A lot. And you are expected to keep up, but due to the time constraints, you cannot keep up with planning and refractoring. So you end up adding stuff everywhere and stuff gets messy. And you keep on piling on small fixes and addendums and abuse functions, until you either run into a dead end where you have to refractor or you miraculously get enough time and ressources allocated to refractor because the change you are making appears large enough to the client/project leader.
So having clean code sadly usually means you spent more money than you should have and more time than you should have. Maybe you can justify it by saying it is for safety reasons or to plan ahead for the future, but with most projects, cleaning up the code after having worked on it for a while is a luxury few can afford.
MrExistence · 1 points · Posted at 21:51:34 on April 26, 2018 · (Permalink)
No. I don’t want to be wasting time debugging, researching something specific, or designing code for some small detail in a program when I’ve already developed it before. If you write it abstract enough initially, you can reuse your old code without wasting time cycling through a process over and over.
It is always good to be versatile and know how to code a feature again from the ground up, but if you create code in the first place where the input and output of each part is clear, you’ve built yourself a tool, and like any other tool, it can be used again and again for a variety of applications. Writing code that is adaptable allows you to focus on the original idea without being derailed or discouraged by the minutia of implementing features again.
wile_e_chicken · 1 points · Posted at 22:00:40 on April 26, 2018 · (Permalink)
No, the old code is a mess.
Minnesota_Winter · 1 points · Posted at 22:01:59 on April 26, 2018 · (Permalink)
Google's lack of managers causes this to be rampant.
BradCOnReddit · 1 points · Posted at 22:03:21 on April 26, 2018 · (Permalink)
"Good" code is written to be read! The old code is "bad" precisely because it can't be easily read and understood. Which side of this line your code is on is a big part of what it means to practice code craftsmanship.
jasonhoblin · 1 points · Posted at 22:05:57 on April 26, 2018 · (Permalink)
every coder has a different style. if you're ona team, you need to conform to the standards set. if this a direct client or project, then yes, there is a good reason to start over. if you're going to be key programmer on the project, it should be your code. if the client or project has a problem with starting over, too bad. they can't expect to invest in a programmer, and fire them, and expect there not to be costs, like rebuilding the entire project.
AntisocTeknoweenie · 1 points · Posted at 22:08:37 on April 26, 2018 · (Permalink)
Stupid, stupid, ignorant, non-programmer question here:
Since code relies on lines and always (?) has some kind of "go to line x" or "refer to line x" couldn't you scan for a mention of a line or lines outside the section to be deleted to be sure it's junk?
If answering this question is too time consuming to bother sating my curiosity, I'll happily accept a "you are missing some core concepts that keep you from understanding" type answer.
kukulaj · 1 points · Posted at 00:35:51 on April 27, 2018 · (Permalink)
Modern compilers will generally warn you if they detect unreachable code. Removing dead code is not the big challenge! Programs are designed to satisfy some requirements. Good design will let a program get updated in some simple ways as the requirements evolve. The problem is that requirement often evolve in ways that nobody anticipated. So all kinds of glop gets hacked in to manage whatever, a link to some other system etc. If you'd know what the requirements were going to become, you could have built in all the necessary doodads. But really nobody is that smart. Few things are as difficult to predict as the future.
alaxsxaq · 1 points · Posted at 22:11:15 on April 26, 2018 · (Permalink)
Pretty much the reason I dumped Perl many years ago. I wrote a bunch of things, then found when I was asked to make changes, that it was painful reading that old code. I rewrote everything in python and never looked back.
Nicolay77 · 1 points · Posted at 22:13:54 on April 26, 2018 · (Permalink)
Definitely not a set-in-stone rule.
Some of my own code is straightforward to read, it actually looks very obvious, but it wasn't so easy to write, and it probably was re-written a couple of times.
In fact, a lot of refactoring work, in many projects, results in pleasant and nice to read code.
CALM_DOWN_BITCH · 1 points · Posted at 22:16:56 on April 26, 2018 · (Permalink)
I'm not a programmer. This is how I deal with everything. Send help.
swentech · 1 points · Posted at 22:17:51 on April 26, 2018 · (Permalink)
Or the old code is a mess. People always learn from their mistakes. Sure you might not understand your old code at first glance but give me a few hours and I’ll understand it fine. It is at this point I’ll be saying wow what dumb ass why did I do it this way.
My favorite story is from a friend in college who worked for Hughes Aircraft on some piece of software that was bloated as a piece of shit. He was confident he could do better so he left and wrote something and ended up rewriting it a few times. Eventually sold out and now lives in a nice house on Manhattan Beach. Granted this was probably the smartest guy I have ever personally known but he was adamant you have to rewrite software a few times to get it right.
jsprogrammer · 1 points · Posted at 22:28:26 on April 26, 2018 · (Permalink)
This doesn't seem true to me. When I learned how to code, I first read quite a bit before I was able to write anything the worked, I'm pretty sure.
holographicolor · 1 points · Posted at 22:32:53 on April 26, 2018 · (Permalink)
The quintessential it's easier to talk than listen
immerc · 1 points · Posted at 22:34:07 on April 26, 2018 · (Permalink)
Imagine if every time a construction company wanted to build a bridge across a river, they tried to keep a lot of the existing bridge around and just bolted new stuff onto it.
You'd have some wood beams, some stone structure, some suspension towers with some iron chains attaching to certain parts of the structure, and some steel cables, some concrete to strengthen certain sections, and so-on.
I think even someone who isn't a civil engineer would see that that would be crazy.
ashishduhh1 · 1 points · Posted at 22:41:23 on April 26, 2018 · (Permalink)
Yeah no. Most code actually is shitty. Well-written code is easier to read.
NianticSuport · 1 points · Posted at 22:41:29 on April 26, 2018 · (Permalink)
I can read the code just fine, I can't write it tho :(
Edit: r
EthicMeta · 1 points · Posted at 22:47:51 on April 26, 2018 · (Permalink)
I consider myself well versed in reading code regardless of the scale of the codebase. How do you present that skill in your resume/interview? Especially considering the majority of interviews focus on arguably stupid shit that has no real application to how they actually code.
jarvitz2 · 1 points · Posted at 22:49:16 on April 26, 2018 · (Permalink)
I am much better at reading code than writing it... idk maybe I'm weird
AGausmann · 1 points · Posted at 22:50:37 on April 26, 2018 · (Permalink)
No, I throw mine away because it is truly a mess and I have better practices now.
nokeeo · 1 points · Posted at 23:23:02 on April 26, 2018 · (Permalink)
For a second I thought Netscape was still around until I checked the article date
thaswayzexpress · 1 points · Posted at 23:40:35 on April 26, 2018 · (Permalink)
Wow. I've never heard or read that last statement, but always thought it. It's the crazy, say what's on their mind, people that change the world
PeacefullyFighting · 1 points · Posted at 23:43:02 on April 26, 2018 · (Permalink)
Fuck you! But yes your right. My first plan starting a new job where I was the only developer was to rewrite everything in my style. They didn't let me, I got pissed and it's kinda working out. I'm a data developer so I planned on translating and documenting the business rules, assigning an owner and getting shit up to vest practice. Instead I spend every day, all day reverse engineering code to see what the fuck caused the problem for the fucking individual report they are running and the fix will break something else they won't run for a few weeks so they won't make the connection. Fuck i hate it and I'm slowly fixing it but I'm still not sure I won't throw in the towel before it's done. You can only put your job on the line so many times with the pretense "what your asking for is impossible with the tools I have" so then they try, fail and you get to do what you want. It's killing me, I've picked up smoking and drinking has increased. One more, fuck you financial industry for using 1980s tech but demand 22nd century accuracy and speed.
drdabbles · 1 points · Posted at 23:52:33 on April 26, 2018 · (Permalink)
I very much experience the exact opposite of this "fundamental law". I can read several programming languages that I could never hope to write functioning software in.
[deleted] · 1 points · Posted at 00:23:19 on April 27, 2018 · (Permalink)
So how do you know the new code will cover the functionality of the old code if the programmer can't read the old code?
righteousdonkey · 1 points · Posted at 01:04:32 on April 27, 2018 · (Permalink)
No shit...
shanrat · 1 points · Posted at 01:25:11 on April 27, 2018 · (Permalink)
Oh yeah no doubt... writing is a breeze till you run it and it doesn’t work and u have to go through it correcting programming typos...
BellerophonM · 1 points · Posted at 01:31:58 on April 27, 2018 · (Permalink)
Nah, they were shit.
[deleted] · 1 points · Posted at 02:17:31 on April 27, 2018 · (Permalink)
reading code to understand it usually means you have to read the database structure, too.
give me the structure of the db, and i can likely tell you what your code is doing.
Juwapa · 1 points · Posted at 02:44:01 on April 27, 2018 · (Permalink)
The Cherokee are the originals.
green20285 · 1 points · Posted at 02:48:36 on April 27, 2018 · (Permalink)
It only takes practice to read code well.
bnolsen · 1 points · Posted at 02:49:01 on April 27, 2018 · (Permalink)
Occasionally I might try to rewrite this type code anyways with the intent of tossing the rewrite anyways. Sometimes you can learn about difficult old code by trying and failing yourself anyways.
mellowmonk · 1 points · Posted at 03:04:56 on April 27, 2018 · (Permalink)
Just like it's easier to write emails than read them.
jecowa · 1 points · Posted at 03:07:28 on April 27, 2018 · (Permalink)
I can definitely read code better than I can write it. But to be fair, I don't really know what I'm doing.
[deleted] · 1 points · Posted at 05:32:40 on April 27, 2018 · (Permalink)
[deleted]
mikeymop · 1 points · Posted at 06:41:35 on April 27, 2018 · (Permalink)
Can you describe the manner at which you approach that
[deleted] · 1 points · Posted at 05:50:24 on April 27, 2018 · (Permalink)
Good friend of mine always calls code bad when he is reading it. He has switched shops so many times and always somehow got a project approved to rewrite something. After a few years quit because the code his coworkers wrote on his rewrite is so bad and they will just repeat the problem with the legacy codebase. He has done this three times already since I've known him.
I never managed to make him realize what the real problem is. I've read his hobby projects and I do think it is fine to overengineer for the sake of it. His code is like some wicked architect/oop pattern smoothie with the most dense writing style I've seen used unironically. Also everything has to be an object. Nothing can be just a simple data structure or function...
P.S.: He has critized my own code and I've learned a lot from it. He really does know his stuff. With great power...
maltesebanana · 1 points · Posted at 06:27:36 on April 27, 2018 · (Permalink)
There are times when it b comes total shit and it's better to get rid of it.
Flamecrest · 1 points · Posted at 07:05:46 on April 27, 2018 · (Permalink)
I have a different reason and it's not because I can't comprehend it. In our Sass files, there are about 6 !important tags per file. The product has about 600 Sass files, if not more. Vendor components have been edited. HTML structure is so unstable it's a fucking miracle we didn't get complaints yet.
Sometimes, there's a perfectly good reason to start over.
IHateAllYourCode · 1 points · Posted at 08:22:33 on April 27, 2018 · (Permalink)
Or you could just use open source components that you know work and incrementally build proprietary functionality.
HackSpirit · 1 points · Posted at 08:41:36 on April 27, 2018 · (Permalink)
Legacy Systems are headaches.
FluffySmiles · 1 points · Posted at 09:06:34 on April 27, 2018 · (Permalink)
Comment the damn code.
Yeah, I know "code should self document", "comments are for pussies" blah blah yadda yadda.
Up yours, I comment the damn code.
And make the function and variable names understandable.
TheFox21 · 1 points · Posted at 09:12:28 on April 27, 2018 · (Permalink)
Is there a part 2 of this post?
crazykid070 · 1 points · Posted at 10:45:55 on April 27, 2018 · (Permalink)
Write more readable code. Plain and simple
vkshah2 · 1 points · Posted at 10:58:56 on April 27, 2018 · (Permalink)
Shouldn't that make code maintenance a costlier service than code creation ?
[deleted] · 1 points · Posted at 11:05:34 on April 27, 2018 · (Permalink)
The real REAL reason is that many companies take the lowest bidder or hand down a timeframe created by non-programmers. This creates the framework to write bad code as there’s no incentive/resources/time to do thorough architecture, testing, documentation, refactoring, etc.
So you are either the person they hired for too little, the person they are forcing to do the work in too little time, or the person who comes in after the “clean up the mess” from one of the first two.
I appreciate that, yes, the above is true. But it is a byproduct of competing in a marketplace where the actual cost of good code isn’t understood.
AceroAD · 1 points · Posted at 11:12:03 on April 27, 2018 · (Permalink)
We are the ones that make code more difficult to read, well writen code is like reading a story but for that you have to use some clean code rules
wjcott · 1 points · Posted at 13:18:50 on April 27, 2018 · (Permalink)
The only time I have ever completely scrapped project code is when the structure/logic was so off base that it would take more effort to fix than to rewrite from scratch. The project in question had passed through the hands of two consecutive college interns and had not been given the proper oversight.
holypig · 1 points · Posted at 16:03:37 on April 27, 2018 · (Permalink)
Wow - an eighteen year old blog post just became the most upvoted article in /r/programming. All hail Joel Spolsky, what a legend.
OneWingedShark · 1 points · Posted at 20:11:29 on April 27, 2018 · (Permalink)
Perhaps if more programming languages were written with readability and maintainability in mind this wouldn't be as huge an issue.
OneWingedShark · 1 points · Posted at 20:22:50 on April 27, 2018 · (Permalink)
There are several big problems that contribute to the codebase being a mess, or perceived as such.
eg C, C++, PHP, and until relatively recently JavaScript.
(Generics, for example, not able to have subprograms, values, and other generics as formal parameters.)
(eg How many "codathon" events are there? How many "designathon"?)
(eg Poor onboarding processes with little to no training; this is tightly related to the more and more common "corporate culture" which is embodied by the term "Human Resources" and views employees as replaceable cogs.)
Riael · 1 points · Posted at 21:13:15 on April 27, 2018 · (Permalink)
Can't confirm, was in a piscine at Ecolé 42 and after 30 hours of no sleep people would come to me asking to fix their sastantua and reading their code and debugging it was way easier than doing it myself.
TheFakeSlimShady123 · 1 points · Posted at 05:00:48 on April 28, 2018 · (Permalink)
Funny little story but in my sophomore year programming class I was lazy as hell and could easily read what basic stuff I had there meant. The catch 22? Most of our assignments were kinda the same but with different variations on the program and concept usually involving a new thing you just learned. As a result I literally just copy and pasted the previous assignment and redesigned the webpage and retitled existing code or added new code in but in the case a line was unused, I just kept it in there all the same. I would continue copying each previous assignment over and over until it got to the point I had pieces of code from like 6 assignments ago in the most recent thing.
But hey I can't complain. It worked, I passed, and it saved me a lot of time to myself to play Line Rider or The Last Stand on Armour Games.com with my friends. Shit was lit.
akito_mashua · 1 points · Posted at 11:02:34 on April 29, 2018 · (Permalink)
No such law exists. The only reason to throw away code written by someone else is because the majority of these situations have something in common: the code is poorly documented if at all. It's pretty hard for people -not only programmers- to get into the mindset of someone else's way of thinking, much alone algorithmic though. I have maintained projects with thousands lines of code (written with ancient programming languages (RTL/2) on VMS systems ) that simply would not be possible without the accompanying documentation set of each module. And the option to throw away that code just was not there for us.
frezz · 1 points · Posted at 14:56:57 on April 29, 2018 · (Permalink)
I don't necessarily agree with this, I think his best point is the point that you are giving your competitors 3 years headway while you don't actually ship any new features.
Most of his points are okay if these are the only problems with the code base, i.e. if you had a two pages function with variables called 'FuckedX', variables starting with m_, then changing midway through, the system was architected in such a poor way, refactoring it is almost the same as rewriting it, except you have to work with your legacy code base.
I also completely disagree with the point that you're throwing knowledge away. If you are rewriting your code base you should be doing it on the pretense that you will architect it in a way that will solve many of your major problems that your original system faced, except you won't have a bunch of conditionals in a two page function to do it.
Usually companies rewrite when you are doing so many things wrong in so many places that the combined effort of resolving these issues is less than simply rewriting from scratch, or your system is doing something fundamentally wrong like having data-loss issues or syncing across clients incorrectly.
TheSnydaMan · 1 points · Posted at 05:59:39 on April 30, 2018 · (Permalink)
Honestly IDE's just suggesting to # explanations could be a way to bump up "readability". Really you could up it yourself by taking more notes in the code. I'm also a novice so I'm not sure if that's frowned upon for some reason.
Queen_Lolita · 1 points · Posted at 03:00:44 on July 9, 2018 · (Permalink)
Commenting on code is so important!
Ever come across hard-coded situations? :)
ideaDash · 1 points · Posted at 12:52:31 on July 12, 2018 · (Permalink)
Here's the reason I like starting over from scratch when I'm programming: It's because a few times when writing my own programs I get stuck, and then when I come back later and start over from scratch I get unstuck or am able to complete the program... at least some of the time. So maybe programmers working on large projects where most of the codebase is not their own prefer to start over from scratch because even on their own smaller projects it seems to help them make progress.
iodian · 1 points · Posted at 15:02:17 on April 26, 2018 · (Permalink)
Wrong. We want to rewrite code because the use case the old codes no longer exists and we want to adapt the code to the ever changing use cases.
dkong1026 · 1 points · Posted at 17:42:24 on April 26, 2018 · (Permalink)
The article was written in 2000. It's ancient in today's internet standards...
I will vouch that it is definitely harder to read code than write it though.
ntrid · 1 points · Posted at 18:43:23 on April 26, 2018 · (Permalink)
This is why I despise rust. Not because it is a bad language. Because people designing rust had every chance to make a readable syntax and yet they opted for syntax full of voodoo magic just like c++ is. No one cares about code readability unfortunately.
Mya__ · 1 points · Posted at 21:20:00 on April 26, 2018 · (Permalink)
Or maybe as you learn new and better ways to do things you want to bring your new understandings to your old work that can be improved?
Joker042 · 1 points · Posted at 22:50:18 on April 26, 2018 · (Permalink)
Muppets still gonna tell you that they don't need to write documentation because their code is self documenting.
[deleted] · -4 points · Posted at 15:26:40 on April 26, 2018 · (Permalink)
Dear Joel on Software,
Please refrain from spreading FUD all over the place.
Sincerely,
Mauricio Babilonio
[deleted] · 0 points · Posted at 10:48:43 on April 27, 2018 · (Permalink)
Bullshit!
xgiovio · 0 points · Posted at 12:29:20 on April 27, 2018 · (Permalink)
Right
Skaffolder · -1 points · Posted at 16:13:44 on April 26, 2018 · (Permalink)
Hi guys, all the problems about starting a new project (code not easy to understand, differents programming languages, lose time for a boring work, difficulty on working in a team of dev) are daily problems for freelancers or for who working in companies.
For this, we created a tool that allows developers to easily create the scaffolding for your projects (and a fully working prototype), in many programming languages, with a source code completely customizable, without writing a line of code, easy to understand and forever free for developers. In 2018 is so strange to spend your precious time doing something that can be automatized. Our mission is to help you to work, reducing your development time that can be spent on the custom part of your new projects!
Our mantra is: "Do not reinvent the wheel!" Try it for free on www.skaffolder.com and if you want, give us a feedback :)
Fabul0usLumin0us · -1 points · Posted at 11:52:35 on April 27, 2018 · (Permalink)
That's complete bullshit. When you're working on a codebase written by underpaid Pakistanis or Romanian interns, the old code is a mess, no arguing about that.