The Best Ways To Simplify Your Code? (dice.com)
Nerval's Lobster writes: Technical debt arises for many reasons—whether moving goal posts, pressure to get code tested and released, high programmer turnover, and lack of documentation. Over time, it can also render code a spaghetti-like mess. But how to deal with it? In a new column on Dice, developer David Bolton offers some suggestions, ranging from refactoring to using compiler inference to increase readability and shorten declarations. While those techniques are straightforward, it's clear that a lot of developers let their code get out of control, and trying to plan beforehand doesn't necessarily prevent the work from getting overcomplicated. It seems like every developer has a go-to technique (or four) for keeping things a little more streamlined. What are yours?
Dice dice dice dice dice.. oh and add some dice.
Bye!
One line at a time.
.
And then there is always this old chestnut... The Big Ball of Mud.
It seems like every developer has a go-to technique (or four) for keeping things a little more streamlined. What are yours?
The mess is just part of coding. Deal with the mess. Accept the mess. Live with the mess. Join with the mess. Speak with the mess. Hear its answers whispered into your head. Nod assent as the mess intones its instructions. Welcome the mess in and let its tendrils throw through your veins. Understand the mess's greater plans and become its corporeal servant on this earth. Hail the mess. Hail the mess. All hail the mess. HAIL!
He's the sort of person who would sell the Red Cross to Dracula.
No really, do not do this unless you actually need to make changes in the area involved. Diving into old code just to tidy it up brings its own set of risks, and they may simply outweigh any 'niceness' advantage.
Instead - black box it. Interface it off. Make your new code structured, shiny and gleaming. Do black box-style testing (inputs vs outputs, almost like futzing) against the old code's API and make sure your interfaced version produces the same. Unit test the hell out of your new code.
Over time, should you actually find a genuine need to, you can then start to look at the black box. Can it be made into a series of smaller black boxes? Can you interface those off too, independently? Cool - do it, one at a time, and use the same approach you used before. Eventually you'll either be left with nicely restructured code or, more likely, nice code that changes often and gnarly horrible stuff that doesn't change ever, but that's hidden behind an interface/library/<insert abstraction methodology here> and works.
Should always weigh the operational risk of changing ugly-but-known-quantity against shiny-but-unknown-quantity. The path of what to do will be different for every case.
Ok... it's DICE but I'll bite... What I have found: IF time allows, the technical debt can be revisited and cleared/reduced. Some schedules don't allow for this, but during non-peak times (like the week between Christmas and New Years) when stuff is slow, I like to revisit some of the bad places and do damage control.
.02
I think spotting these issues, and giving the developer enough time to re-visit the bad section of the code is ESSENTIAL to maintain a relatively clean code base.
Code reviews can help, but the project deadline pressure-cooker usually prevails. My
The best way is likely by not reading a Dice article.
But seriously, the main problem is that many developers don't give a shit about the quality of their work and no one notices or does anything about it. It's not a matter of learning a technique.
If there's no rigor around what you write or how it gets tested, software will turn out shitty. If the development issues can't be fixed, it's often easier to just lie to the client or use hacks and workarounds to hide problems.
The fault for this lies with management. You need to police your developers but also treat them well enough that they're invested in writing good stuff. You need to hire good people and provide your mediocre developers with good examples to follow. If your developers think they're going to be fired long before they have to maintain anything, they'll probably turn the shittiness up to 11 out of spite. if they anticipate quitting over compensation or overwork or work-life balance, how good is their code going to be? If they hate your guts because they're on a visa and getting taken advantage of, how good is the code going to be?
It seems like every developer has a go-to technique (or four) for keeping things a little more streamlined. What are yours?
You get the job done as fast as possible and let the Indians worry about it when they get it.
See, you'll be on a project with an impossible deadline; all the while upper management has been wined and dined by the Tata/WiPro/CSC sales people and are gonna offshore the project for the production and maintenance phase. And many are just offshoring everything.
So, get your stuff done on time, learn everything you can and find another job. Because if you stick around, you'll be canned and when you are unemployed in this profession, you are unemployable - if you're any good, you'd have a job.
And do what you can to get into management before you're 35.
And if you're really smart, you won't fall for this STEM career hype.
Are you sure you know what those terms mean? (e.g., Fast but simple solutions often create technical debt.)
When your question gets closed on Stack Overflow, then try to ask it on Slashdot?
Frankly, if your code is constantly getting out of control and becoming unreadable, you are not doing professional work, you are doing amateur work (and yes, I know that there are plenty of paid professionals who do amateur work. We've seen stories from Trend Micro programmers here recently on Slashdot).
It's not a set of rules to follow. If there were a mindless algorithm to follow, then a computer could do it. Instead, when you are about to write code, always ask yourself, "How can I write this in a way that future programmers can understand it?"
"First they came for the slanderers and i said nothing."
has a go-to technique
How did they know my technique!?
Just finished "Hello World" then eh? Good for you, time for the next example in the tutorial...
"File to fit, pound to insert, paint to match" - Aircraft Maintenance 101
Understand the problem it addresses better.
Post may contain irony: discontinue use if experiencing mood swings, nausea or elevated blood pressure.
Developer David Bolton has moved on from Dice and the remaining authors have been left scrambling trying to pull his notes and articles etc together to generate new content. They report having difficulty understanding how he cobbled together the disparate information into existing articles and have advocated just rewriting the articles from the ground up so they would be easier to maintain going forward.
Next!
Kidding aside, simplicity is the art in programming. It comes from understanding, not methodology. The question is similar to the one posed to Michelangelo: "How do you know what to cut away?" And the correct response is about as useful as Michelangelo's: "I just remove everything that doesn’t look like David."
Eliminate error handling.
No one, absolutely no one, wants to read your shit articles. Stop pumping them into the feed.
Basically, I used to refactor constantly whenever I maintained code.
When sarbaynes oxley was passed, every change had to be approved by lower, then mid, then upper management in a series of 6 meetings. Doing anything except exactly the enhancement they wanted was virtually impossible. There is never a good cost/benefit for cleaning code when you think that way. Any change outside exactly what was approved would get you written up.
I went into management. Programming ceased to be engaging. it was easier to argue for code cleanup a couple times a year as a team lead than as a programmer because we had two people saying it would be beneficial.
But...
*Changing non-meaningful variable names
acnum to AccountingCustomerNumber
This was the number one way I helped other programmer's fix their bugs. I would just ask- what's this- okay rename it. what's that- okay rename it. And after a short time (20? 30?) minutes they would see the bug themselves. After comments like, "Why do I need a long name- we only use this variable a few times.
Refactoring any routine where the actual code was over a page in size into subroutines.
Running performance tools to locate "hot spots".
She was like chocolate when she drank... semi-sweet at first and then increasingly bitter.
Don't get a development team larger than the task really calls for. I've seen so many chunks of code that really has not much to do be horribly convoluted because they split up the work amongst more developers than it makes sense to have working on it.
XML is like violence. If it doesn't solve the problem, use more.
It is in having detailed requirements and performing proper testing. Good requirements will lead to good tests which will detect most of code defects. Doing structural coverage will also find not needed code.
When I take shortcuts because I am in a hurry, I try to leave breadcrumbs. I put comments that start with the string "FIXME" and then write a quick sentence or two explaining how I would do it if I had more time. Then later, when I do have time, I can just grep for "FIXME" and find a list of things that need to be fixed. Those comments save me a lot of time, because I have an explanation from when it was still fresh in my mind, preventing many "WTF moments".
These books provide much better information on the topic and deserve a place on your shelf alongside the GoF's Design Patterns.
+4 insightful? Is everyone with moderation points 14 year old?
My first program:
Hell Segmentation fault
Do you think that lawyers sit around lamenting the complexity of the legal system that means cases take years and thousands of hours of work to decide? Or that accountants sit around wishing the tax code was simplified to the point where a regular small business owner could prepare their returns themselves?
It may be a good thing for humanity if programmers create less work for themselves, but it is certainly not a good thing for the programming profession in the money-go-round that is banker-capitalism. It is a stupid system, but I can't really see it being changed any time soon. Sometimes I imagine the accountants/lawyers who pretty much run the economy just have a big laugh at idealistic programmers trying to do 'good' in their jobs.
My advice is that if you want to write good code, go work for yourself, where you can profit directly from reducing the time it takes you to maintain your programs. Otherwise, my advice is work for a really big hourly rate and don't get conned by 'job security' and a foosball table.
#include main() { long long P = 1, E = 2, T = 5, A = 61, L = 251, N = 3659, R = 271173410, G = 1479296389, x[] = { G * R * E * E * T , P * L * A * N * E * T }; puts((char*)x); }
I think what everybody is hating on is the undisclosed relationship. Nerval's Lobster is a shill account. This is not ethical business practice.
One of the checks I do is to have a non-programmer just READ my code. If they can make any sense of it (Think variable and function names) then I continue. If not, I rewrite until it reads like English (with extra stuff in the middle :-)
I also have SHORT (as in a single line or perhaps two) comment block at the start of anything that isn't immediately obvious. This adds to readability.
I have code blocks that are more than 10 years old, that I still refer to and which I can make out the intent and the execution without issue because of these two very simple techniques. '$a' doesn't tell me anything. '$account_name' does. Stop trying to limit your typing load.
Other thing I do, which I find missing from a a great many things; Check your inputs and your return values. As much as this is Programming 101 level stuff, it is remarkably absent from so much code. How is it that SQL injection works at all?
+4 insightful? Is everyone with moderation points 14 year old?
Apparently, and it ignores the simple fact that Dice probably sucks small and medium dicks as well.
So, in keeping with the thread topic, I'll simplify the original statement: Dice.com sucks dicks.
It must have been something you assimilated. . . .
1. refactor
2. while you do that, divide up the code into modules that is a black box from outside
3. refactor those boxes as needed (split into more as needed)
and don't be afraid to do that before your program is finished, if it seems needed.
The time you save on a refactor is often quite a lot, so you shouldn't be too afraid of doing it.
Also making boxes like that helps testing.
But then again, I thought that was already what most projects did.
It's kind of a central point in most programming paradigms (both functional and object oriented).
I agree about code reviews: in fact I consider them essential in a team environment and wouldn't want to work in a code base where they will not be consistently held, at least going forward. Then the team can agree on some kind of standards and I recommend that the team develop a checklist for things the reviewer should check, where near the top of the list is: "Would I want to maintain this, and could I understand it easily if I came back to it years from now?". Also somewhere on the list is: "How was this tested?". Nothing ever gets into the master branch without such a review. Ideally the review is asynchronous, at least the first pass, to help see if the code is clear without its author explaining it.
Also, the coder should review his own code first with that in mind, before sending it to someone else to review.
Otherwise code becomes a mess. On a team small enough to enforce it, things can go much better.
A Free, fast personal organizer for touch typists: onemodel
Dice.com sucks big dicks.
I'm guessing that Dice then is making someone or some people quite happy. A lot of guys seem to devote considerable effort towards getting their dicks sucked, so I don't really see how it's a bad thing
SJW n. One who posts facts.
If you're gonna suck dicks, GO BIG OR GO HOME
Dice.com went big, and OP was recognizing their bravery and determination.
Cheers, OP, I'm with you!
but during non-peak times (like the week between Christmas and New Years) when stuff is slow
Best week of the year because no one is there, and you can work on whatever you want.
"First they came for the slanderers and i said nothing."
Don't be clever. Most of us aren't paid to be clever. Follow the KISS principle. Be kind to the maintenance programmers and keep classes and methods short and to the point. After all the maintenance programmer might be you. Methods more than 1 screen in size are suspect. Avoid lasagna code.
Just a few rules I try to use.
putting the 'B' in LGBTQ+
Any principle that is good most of the time can be mis-applied. I have worked with developers who loved linq and would use it to compact loops and such down to a line or two of completely impenetrable gibberish. The long-term maintenance cost significantly outweighed the elegance of dearth.
I have also seen a simple multi-step script be broken out into a series of objects with an inheritance hierarchy...what was previously 50 some-odd lines of simple and straightforward code became 200 lines broken out over three files, with a slight reduction in performance (we tested it for that), and a bug was introduced in the process.
Whatever it is you plan to do...make sure you have a good reason for doing it, that whatever rules you are following actually make sense in your specific context, and that you have it all covered by good testing.
Just delete all white space and line feeds and your code will be much more stream lined. Removal of all comments will also significantly improve information density as well.
It's a feedback loop. Post stories in a manner that treats its readership like 14 years old, and we'll act 14 years old; which I'm fine with BTW cause being old sucks ass.
Life is not for the lazy.
Write it in assembly.
You should aggressively get rid of developers who 'make a mess' in order to 'get things done'. Such people are outwardly productive but are ultimately a negative for your project because you have to rewrite their garbage. Recognize them as early as possible.
> Make sure you understand the implications of every line you change (yeah, that's slow).
A complementary technique I used recently was to make sure I did NOT understand the code. I could understand the implications of changes, avoid any side-effects, by not trying to understand what the code did and instead applying mechanical transformations. I got a new job, working on a code base I'd never seen before. I made some significant improvements by refactoring code while making sure I didn't understand anything about what the code did. Basically, I saw something like this:
for (i=0; i = 1_000_000_000; i++) { ...
foo = 'bar';
fi = 'bee';
printf(foo, fi);
}
I could change that to this and know it was write, without understanding anything: ...
foo = 'bar';
fi = 'bee';
for (i=0; i = 1_000_000_000; i++) {
printf(foo, fi);
}
Similarly I could cut-paste blocks of code into functions, without caring what that block of code did - I only cared about which variables it accessed.
Or when I saw this:
cnm = get_customer_cumber()
I could then rename the variable via search and replace to cnm to customer_number throughout the scope. I don't know or care what a customer number is, but I know "cnm" means "customer_number", so I can do that search and replace.
So I'd say you can choose to either a) understand the code well or b) assume you don't understand it at all, and therefore make provably equivalent transformations, such as renaming, properly extracting functions and subroutines, etc. What's dangerous is when you make changes based on an imperfect understanding, when you -think_ you know what the code does, but you're wrong. You can go a long way while knowing that you don't understand it.
Make your APIs sane, make ownership obvious and only abstract as far as strictly necessary. And for god's sake don't use PImpls - they might make headers cleaner but they make code twice as hard to maintain and debug.
Taking a little longer to do the job right first time is a great idea, but if the boss is a micromanager who wants everything done yesterday it just will not happen that way. The only way in this case is to leave yourself clues to ease the pain when the next disaster hits.
I'm being a little unfair though: most bosses are actually not that bad (though micromanaging imbeciles do exist). However what most bosses do not understand, in my experience, is the value of *thinking* about how to write the code. Not brainstorming, not googling like a million demented monkeys hammering on a million typewriters, but stopping for a brief time, staring blankly into space and just thinking about "how can I do this right?". This sort of introspection is the best way to write good code first time, and it's also almost guaranteed to get the boss on your back asking why you're not working and making inane suggestions about talking to golden boy two desks over.
What you suggest is the right way to do it, but it depends on having time allocated to doing it the right way and a manager who gives a crap about anything but squeezing out more features faster.
Otherwise, you become just that guy who never meets the deadline. Shortly after, you become the former occupant of cube 230B.
.. as much as some companies incentive code addition. If a programmer is paid using a metric of LoC then, I think, something is wrong. There is just as much work done in removing code as there is in adding it.
The flipside is important, too, though: Just rewriting good eloquent code with "clever" oneliners is absolutely wrong.
Code that has to be there should be eloquent and well-documented. Code that does not need to be there should be removed.
remove nospam. to email!
4 out of 5 of his suggestions were so simple the you could have gotten them out of any of the 10,000 blogs on 'improve' your programming, Refactor, use OOP, Unit Test and use Version Control. Any programmer that has more than an ounce of experience is already doing this.
The fifth suggestion was the one that was just plain stupid. Using auto/var for declaring variables is the intellectual equivalent to Visual Basic's, Option Explicit Off. Sure you could do it but why?
Or just write it correctly the first time? I know it may be harder and more time consuming, but you'll get further in your career if you do.
Depends, in R&D I write an awful lot of throwaway code - maybe as much as 80% (depending...) but, at the outset, I can't tell you which 20% will be kept and used in the product and which 80% ends up being "investigatory."
Sure, you could just rewrite the 20% from scratch and "do it right," but that's not as efficient as reusing the proven test mules - which usually aren't in too bad of shape, if you trim off the FIXME: and TODO:s.
In my career, being able to show working code, quickly and easily, is important - much more concrete than sitting in a meeting and drawing bad sketches on a whiteboard while waving hands and attempting to explain things to people who all visualize verbal explanations differently.
Once I can't bear to look at my old code any longer, I don't even feel like investing the time in trying to bring it up to snuff. I just rewrite it, which usually works out well because I get more experienced over time and have thought of different approaches that could have been used originally. Fortunately I'm almost always the sole author and I deal mainly with embedded apps, so the code is fairly short. I'd never dare to use this approach with more complex programs, assuming I could even talk anyone into letting me.
Obviously, but if computer programs are written by humans, who are, unfortunately imperfect, and make mistakes. Sometimes we don't think of everything right away, and a better solution may simply not be known at the time of initial implementation. That's not anybody's fault.
Anyone who expects a good programmer to be someone who never make mistakes (or at least who has already made all of the mistakes they ever will by now) and will never have to sometimes do something completely over again from scratch because they did it wrong is living in a fantasy. A good programmer is not someone who doesn't make mistakes, it is someone who can *LEARN* from the mistakes that they do make.
File under 'M' for 'Manic ranting'
Best thing I think, which will never happen, is to keep the work load light so that the team has actual time to spend making the code better in the first place as well as time to go back and rewrite older code. But too often everyone's on a death march to meet deadlines, you can only add features and fix bugs and any redesign or rewriting isn't assumed to help the bottom line. A lot of bad code I see is not because the programmer is bad but because they're being forced to add the code quickly and move on to the next task quickly.
When I want to refactor code, I first make sure we're working in a programming language that is suited for refactoring. That usually means it must be Java... nothing comes close in refactorability. It certainly rules out anything that isn't extensively checked by a compiler (eg. Javascript) -- there's always code paths that aren't covered in tests, and you rely on the compiler to warn you of potential problems in those.
Second, I make sure there are good tests available, not just unit tests but also integration tests. This is usually the case on projects I work on, or I won't be sticking around for long.
Third, I do refactors in tiny incremental steps. Usually it's like "remove one method", "remove a parameter", "add/remove an interface", "delete a class", "split a class", "move a method", "make a parameter required by moving it to a constructor", "make something immutable by removing its setter".
As soon as you do one of those, there are gonna be errors detected by the compiler. I ignore the ones in tests and quickly check the ones in real code to see if the refactoring does not have something I did not foresee that would be tough to fix. If there's something unforeseen, I think about what refactoring would be need to be done before this one that would make that easier to fix later.
Once it looks like it will work, I fix the errors in one class, then in its test, then run the test to see if nothing broke. Then I go to next class, until all the errors are gone (usually this takes around an hour for 50-200 errors when I started).
I then run all the tests, and if everything is ok, I make a commit of that refactor step. Then I start with the next incremental refactor step. At any time, I can merge the stuff with master and stop and work on something else, while still having some small benefits of the refactorings done so far.
In this fashion I've refactored existing code bases to use a different time/date system, refactored code to use two different models (instead of a unified one), made models slowly immutable (it's amazing how many problems you discover when you start doing that), etcetera.
If you need to aggressively hide the implementation there are other ways than doubling up the number of definitions and classes. Pimpls are just annoying, particularly when they're in code which has no reason to use them - I could sort of understand the purpose if the class was a library of some kind but I've encountered them in internal code where their only purpose is to be a pain in the ass when the class(es) need to be modified.
Implement first, optimize later! Don't pre-optimize, because optimization usually introduces code complexity. A lot of the time your code will be "fast enough" or "small enough" to get the job done. Don't get too clever. Also, plan things out at least a little bit. Don't just start coding. Draw some pictures, talk through some use cases... try and ferret out and plan for some oddball corner cases before your testing finds them.
"False hope is why we'll never run out of natural resources!" - Lewis Black
Nice work in keeping the first product just below 2^63 - 1, and avoiding undefined behavior that way. However, it looks like it will only work in a little-endian environment.
"When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
YOU WIN THE INTERNETS. That is all.
Seriously, funniest thing I have seen in days!
What you suggest is the right way to do it
It is almost never the right way to do it. Specs change, or are incomplete, or don't even exist. So it is better to hack up something quick, make sure it is what the customer (or your boss) actually wanted, and then go back and do it "right". It is silly to waste time making code "perfect" when it most likely will be thrown out.
Dice hate aside, it really is a pretty lame click-bait article that could have been written by a bot. It's not bad to spark a discussion on Slashdot though so I'll bite. The first thing that comes to mind is DRY. Knowing when you are RY isn't always easy though, and there are some interesting tools out there that claim to be capable of detecting patterns via static analysis. I have to confess I haven't used them though. I'm wondering how big an obstacle to reduction is found in the "prestige" of "managing millions of lines of code". If somebody came along, audited it, and told them it was really just a massive macro expansion that came from 2500 lines, they might not be so happy.
For all intensive purposes, "whom" is no longer a word. That begs the question, "who cares"?
That also depends on management. If the management is any good, they'll make it clear when a spec should be treated as final or tentative. They'll also give you time to do go back and re-do it right if/when it becomes final.
Otherwise, you have no idea if it is fixed or not and you will NOT get a chance to replace the spit and baling wire later.
"Tis a fine barn, but is no pool," Early Simpsons. Does you thing really need a blah--just because everyone else is doing it. Do we really need a internet connection for a notepad application? How much work is the "Managers" and now, the "Centers" doing?
Just don't put useless crap no one needs in your software.
https://www.youtube.com/c/BrendaEM
Change jobs!
"What you suggest is the right way to do it, but it depends on having time allocated to doing it the right way and a manager who gives a crap"
On one hand, you already have been told that's not usually "the right way to do it" since allowing for features to go along and see, once they are tested in real world, which ones will stay and which ones will not is usually the best way to go.
On the other hand, unless your manager is both a micromanager *and* technically competent, don't think about what your manager can do for you but what can you do for your manager.
If you think a bit about it, he's completely at your mercy and the code can not be "done" till you make it "done". No, not when you *say* it's done, but when you *make* it done: don't think about refactoring the code and refactor the way you write it instead, and even if your manager is the kind of "you say it's a mock up, but it looks good enough for production to me", if there's no box, no screen, no output, it won't be done even for him. Instead of coding "the happy path" first and then go after the corner cases (and never have time for the corner cases), go with the inner parts first and make your code so it doesn't do anything useful till you deem it good enough (and don't fool yourself: it's probably "good enough" quite before you usually think).
Each time you rewrite a function in a different way the inherent risk of bugs increases. As such, you'd want to undergo all the sdlc retesting, which does add overhead...
Use Sonar or other code checkers.
After you resolve the critical things (i.e. circular dependencies) etc there, life will be simpler.
Since your code is shorter, other people can read and understand it easier
Assuming a simple null = 0 check: object obj = 123; int somenum;
Short: somenum = obj is int ? (int)obj : 0;
Long: if (obj is int) somenum = (int)obj; else somenum = 0;
I would argue the Long one is easier to read.
Short does not mean try to condense it... you can stick everything on one line to achieve that and it will be the most illegible and hard to read format.
Ternary conditions are not a way to make your code short, you should consider them equal in length conceptually but more concise - that can be good or bad depending on the complexity of the statement.
That's not to say there is no value in trying to keep some things concise for legibility, but there is a difficult balance between terse and concise when doing this... I think the important thing is to focus on clarity, this other attributes are just ways to achieve that, they should not be used for their own sake:
Short, concise, simple (as possible) and DRY can help achieve clarity; using single letter variables and ternary statements for everything will achieve a short terse and unclear mess.
Judging from the way most programmers "refactor", the solution to complex code is to replace it with even more complex code, because something that employs as many technologies, buzzwords and frameworks-of-the-week is obviously better.