Are You Proud of Your Code? 682
An anonymous reader writes "I am downright embarrassed by the quality of my code. It is buggy, slow, fragile, and a nightmare to maintain. Do you feel the same way? If so, then what is holding you back from realizing your full potential? More importantly, what if anything are you planning to do about it? I enjoy programming and have from a young age (cut my teeth on BASIC on an Apple IIe). I have worked for companies large and small in a variety of languages and platforms. Sadly the one constant in my career is that I am assigned to projects that drift, seemingly aimlessly, from inception to a point where the client runs out of funding. Have any developers here successfully lobbied their company to stop or cut back on 'cowboy coding' and adopt best practices? Has anyone convinced their superiors that the customer isn't always right and saying no once in awhile is the best course of action?"
TIME! (Score:4, Interesting)
From a pure Computer Sciency standpoint, remember that no code is ever completely bug-free...its mathematically impossible. Testing does not prove the absence of bugs, it only proves the presence of successful use/test cases.
But the number one thing holing me back is time. When I'm coding on the company's dollar, there's only so much time to spend in design, in writing test cases, in having someone peer review your code. And thus, there's just not enough time to spend doing things in the absolute, 100% correct way. There has to be some compromise.
I suspect that even if I had time, I would run out of mental energy first.
Work for engineers not software companies (Score:3, Interesting)
They understand the need for excelent documentation, rock solid requirements and that you don't get halfway in a project and change its direction (ie, "sure, the Golden Gate is halfway done, but we'd actually like it to go from Lime Point and meet up with the Bay Bridge around Treasure Island Road"). They understand that some things take half the time to do but are four times as expensive to maintain, and they prefer quality over quantity.
Least the ones I worked with
Do some open-source coding to feel clean again. (Score:5, Interesting)
The product I work on at work features all three. It can be 'interesting' to maintain sometimes. That being said, it's frequently possible to rewrite sections and management sometimes listens to the programmer types and has let us restructure things sometimes. For example, we've mostly gotten rid of the RPC stuff.
When I want to satisfy my urge to work on good, clean code, I do some open-source work. Open-source tends to have that, because nothing else tends to work for very long.
Re:Something to note about other people's opinions (Score:5, Interesting)
When I look at my own code it's a mixed bag. The stuff that I earned the most money with is actually programmed quite bad, some of the most elegant stuff I wrote is sitting unused on the shelf.
I find that in a commercial setting I'm far more inclined to 'cut & paste' to keep moving rather than refactoring just to save the time. Sure, it leads to maintenance headaches down the line and I quite often just scrap stuff and rewrite it rather than figuring out what it did and why. Tools evolve at such a tremendous clip that I don't think the lifespan of code is anywhere near the point where it could be justified to spend say an extra week or two to get an algorithm tweaked to perfection if the next release of the tool or framework is going to have it built in anyway.
Faster machines also lead to sloppy code, I'm running a lot of production stuff on uncompiled PHP, whereas in the past I've rolled out code in assembler because I could beat the C compiler by a couple of cycles on most tight loops.
Times are changing, and that is the biggest 'driver' against 'clean' code, it won't be long before the actual code will start to disappear. For some environments that is already happening.
Oh well, old guys like me will find employment writing for embedded systems, which are about a decade behind the curve.
Re:Something to note about other people's opinions (Score:5, Interesting)
Here are some pet peeves of mine involving dealing with other people's code. I don't think many of these are subjective either.
All Code Sucks... (Score:3, Interesting)
There is no Holy Grail of code.
What is good coding style to me, may be anathema to you.
Ok, there is utterly shit code (which probably accounts for a fair proportion of all code if my life experience is anything to go by), then there is 'run of the mill' code, then sometimes rare glimpses of 'great' code.
Great code for me is when you see it and understand the programmers intention, and you think: a) I would have done it that way, or more likely b) if I was smarter I would have done it that way. You learn from great code, if you're already a good coder.
I think the greatest obstacle to 'great' code is 'language fascism'. Some languages are better than others, that's true, but they way some people carry on you'd think it was only possible to write 'great' code in their language of choice. This behavior is generally exhibited by those that can code in one (or at most two) languages only.
I'm generally proud of my code and am happy for others to scrutinize it. All that means is that I spent the time to make it as good as I could withing the prevailing time/cost constraints.
I used to write a lot of assembler. Some of my colleagues used to think it was cool to use obscure instructions, in unintended ways, just to show how 'cool' they were at flipping the registers. I never subscribed to this idea and always used 2 or 3 common instructions instead of one 'neat' instruction. Performance never seemed to suffer and maintenance programmers were eternally grateful.
Re:More Design (Score:3, Interesting)
The continuous feedback of easily understood information as to what the design is and where you are goes a long way to keep the client from becoming concerned and thinking it's a waste. It's actually a method for speeding things up towards a positive end.
Pride fades with time (Score:5, Interesting)
Usually, when I unearth the code 6 months later I wonder if there's any way to get this horrible piece of hacked crap out of the CVS somehow...
It's just that, well, you learn. You improve. Yes, even after more than a decade of coding, you still learn and improve. You learn new tricks, you learn to use new libraries, and you discover better and more efficient ways to use them by using them. So generally, yes, I'm proud of my code. For a while.
Actual Software Engineering (Score:4, Interesting)
In what other line of work does principal construction begin before the customer has defined what it is they are ordering?
A software is not a product in itself. It's not like an "apple" or an "orange", it's more like a "building" or a "vehicle". A building and a vehicle can be the solution to many different problems. A truck doesn't necessarily solve a customers problem if he's looking for a way to transport people in style from A to B.
But while I think that most people understand this, they have a very fuzzy and indistinct concept of the cost of changing the specification once construction has begun because you can't walk the customer out to the building, point at the construction and say: "To make the changes you require we will have to tear out that wall there, remove all the concrete laid here, that will require a week and scrap more than four tonnes of construction material".
This is where software engineering comes in: With a good model and by sticking to the principle that you begin with a specification from which you construct a series of test to see if the specification has been fulfilled. From the specification a design is made. The design specification is used to implement tests to see that the design has been followed. From the design the code is written and on the code the tests are run.
Now when the customer changes the specification you can look at the design and the code and see (hopefully) how substantial the changes will be and what the cost will be. Your customer will thank you for being more accurate in your estimation, for pointing out the costs (which is the only thing your customer will care about, remember that time is money and is just another type of cost).
I have so far only worked in one workplace where this model was used and it was used very successfully in my opinion. Writing all those documents surely sucked, until it came time for implementation, which was frighteningly quick and painless. The ultimate pride for the well documented, well planned, well concieved and tested code has made me utterly incapable of being satisfied with any other way of working (which is why I've switched jobs a lot).
Changing to a structured approach to working is costly, but the benifits are bountiful and will ultimately save money and time. I can almost promise that while you might lose a customer or some goodwill of a few customers in the interim, in the long run, the customers will flock to you since you are delivering on time, the functionality they asked for.
good luck (Score:2, Interesting)
Good luck with that one. Successful technology companies use pie in the sky marketing. Reality does not sell. When you are not saying yes I can do it faster and better then you are whining as far as CEOs are concerned.
I have a great career and made lot of money writing crappy code. My bosses have always loved it because I am fast to produce an end result. I call it prototyping and constantly remind my employer that I am creating a demo of what can be done. But in the end the demo always goes into production. I have seen several programmers much better than I get fired because they could not bring themselves to lower standards. I guess I'm just a code slut.
Re:Something to note about other people's opinions (Score:4, Interesting)
It comes from learning Z80/8080 assembler first, before BASIC, before C. Until that point, I knew a few macro languages.
In my mind, I'm still in a 32K machine, living with the OS, writing strings to hardware ports, and using my own interrupt vector code in concert with the host cycles to get work done.
When I work in C or C++ (heaven forbid #), there's a link list in my mind about array conservation, minimizing strings, using hashing and strict Booleans to get a job done.
No, I'm not an embedded systems coder; I just end up thinking like one.
My comments used to go thru an assembler, and I'd look at the code and try and re-optimize it. And when my code would explode, it would explode to unrecognizable shards of crap until I learned atomization (objects) and resource re-entrance. Now when my code doesn't work, my deadman's switch monitor twigs, which backstreams messages. It makes coding highly involved, but vastly more productive because *I CAN* reuse my code.
I worry more about the OS than my own code; there's so much that's not predictable in operating systems today. They should do more work with smaller kernels and leave modularity out of the kernel. Just my 2c.
Re:Something to note about other people's opinions (Score:2, Interesting)
This might be harsh, but the solution is easy... (Score:3, Interesting)
Having problems with bad interface? Design better interfaces. Jumbled, complex code? Refactor it. Slow execution? Improve the algorithms. There's basically no project that takes longer time by doing things right, more often than not the opposite is true. A good refactor can save tons of time.
There's no magic bullet, however much support you get from superiors or coworkers. The only thing you can do is simply write better code.
Re:Something to note about other people's opinions (Score:3, Interesting)
I started looking up the terms being thrown around here lately for coding...'agile', 'cowboy', etc. I'd never really heard the terms much.
Do places really have all this stuff laid out for programmers? Standards? Naming conventions, development cycles? How do they find the time for that? I've never really seen timelines that allowed for that much time and long deadlines before.
I've heard the theories, but, have never really seen them in practice. How many out there do all of this...or just part of it, or moreso, pay it lipservice, and jump in there and write as you have to to get it working and out the door to meet a deadline?
Re:Something to note about other people's opinions (Score:4, Interesting)
Development Methodology (Score:3, Interesting)
Your deliverables (above) will be a part of your project charter. You will also include stuff like: a list of stakeholders, RISKS AND ASSUMPTIONS (such as a deadline not being met, etc.), testing, and of course "Success", which will be a list of metrics that define a successful product (ie: it can generate payroll checks, it can print report A, etc). Then, take your project charter (look it up on google) and put a bunch of lines on the bottom for you, the team and the management and the key users to sign off on. Do not start work until it gets signed off. Then make a copy for yourself and file the original with the project documentation. Work and complete all the features to be developed. At the end, take the project charter and make sure everything is fulfilled, then give it to the "customer" and have them sign off again for completion (after you demo the software).
Usually scope creep means poor project management, and as a developer you can't expect anyone else to do it. Just do it, you will be very thankful you did. Also, if it's a short project, try something called Quick-Kill [ddj.com] project management. Large projects need a better methodology. I use one I made up that's based on the quick kill and some microsoft stuff, with some unix version control stuff, and oracle business process analysis stuff... Over time you will develop your own methodology and become a star senior programmer making $300,000 a year.
Have fun
Re:Something to note about other people's opinions (Score:3, Interesting)
It was written in Borland C 2.0, shoved into 3.0, dragged across to Visual Studio 6, then keelhauled into 64 bit support (from 48 bit initial functionality). We re-used that codebase for every project, tweaking and modifying, forking where appropriate per product family. Management asked what it would take to make it more maintainable and myself and the one other developer still with the company said: 8 months of dedicated time for one of us, with guaranteed time for code reviews of 2 half days per week for the other developer to provide a second set of eyes. Naturally that didn't happen. FFwd a year and the division is being split from the parent company with > 30% layoffs. Upper management decided who went and who stayed with a rather broad brush. Since I was technically "maintenance" and the other developer was old enough to retire we were both cut (she got a carrot to volunteer to retire). So who is developing and maintaining the code now? My old boss. Less than a month has gone by and I'm already getting "helpdesk-ish" calls on the code. Once they are fully split from the parent company (for which I am still employed, but in a different devision now), my consulting rate will kick in, and boy will it be nice.
Moral of the story: When code *is* re-used, it usually gets ugly. A clean re-write is not always a bad idea, and if your devs are asking to be allowed to re-write something you should let them before you can them...
-nB
Occasionally I ... (Score:4, Interesting)
Then I go through a totally re-write the code from end-to-end. I look for unused sections, variables, etc. I re-order all the logic so that it is logical. Then I test for the necessary period of time.
Since most of the code is already written, I start by writing out the business rules and I make the order of the code follow the order of the business rules, more-or-less. I put ALL of the business rules into the code as comments. I also send the rules to the client/boss/myself/others.
Doing this just once a year, on each critical section of code actually saves me much more time than the initial investment, so everyone wins.
Re:Something to note about other people's opinions (Score:4, Interesting)
I do otherwise agree with all your points; the best place is a middle ground between agile's self-documenting and the traditional ZOMG COMMENTS. At my (non-agile) workplace, we document at the top of each function what the function does and what it takes and returns, as well as documenting any complex or unintuitive block of code within a function. (The ideal would be to avoid unintuitive code entirely, of course, but this is not always possible when dealing with things like VoIP goo.)
legacy (Score:4, Interesting)
One such system has two very different kinds of programmers. One kind produces very small, tight, elegant code. Each line may be complex, but there aren't very many of them. Another kind generally codes for conceptually easier tasks, and has a verbose style. Individual lines are trivial assignments, but there are sometimes thousands of them.
The elegant code is MUCH more difficult to debug. It's also, generally, broken much less often. The verbose code is generally very easy to fix.
But i've gotten an appreciation for other ways to do things. And, there aren't nearly as many of us 'elegant coders' out there for replacement. But i still don't see how some apps can be accomplished at all without us. This appears to be language, library and tool independent. Fred Brooks seems to have something to say about this.
I'm firmly in the realm of 'elegant coder' myself. My favorite piece of late is 750 lines of very dense code involving a seven dimensional hash (but sometimes six - it varies) with dynamic indexes. It replaces a 25,000 line chunk that had to be changed every year. The new bit never needs change. However, despite ample documentation and three tutorials, i was unsuccessful in showing the new team how it worked. The new system has designed this bit out completely.
One thing about both projects is that the employer either started a project to replace them, or actually replaced them. In both cases, it was an incredible amount of work and expense to do this. Millions of dollars. It would have been both cheaper and better to fix their problems, and update their user interfaces. At least, once an appropriate programmer was found. Oddly, we have at least two on our current team.
Oh, yes. The replacement projects went over budget and were late by at least a factor of two. Much more, if you consider that something like half of the functionality was removed. And there seems to be one chunk that the new team doesn't seem to be able to deliver. Perhaps the new team needs an elegant coder.
Excuse me if I'm rambling, but... (Score:4, Interesting)
So yes, comments should say WHY more than WHAT (specifically) a line or block of code does. A short narrative is usually the most helpful, ime. Basic description of what the method (or even a crucial line if it's the least bit unconventional or otherwise unintuitive) does (in bird's-eye-view terms / how you would explain it to a non-programmer), and WHY it is doing it if that purpose isn't obvious from WHAT.
And I also say (most of) my predecessors' code sucks, but in this case, it does. There was one guy who seemed to have a decent idea of what he was doing, and I think he got burnt out by the complete buffoon of an "IT Manager" they had at the time (hurray cronyism! He still works here in his own project group because he's friends with the big boss). But the other guys...one would have actual end-user visible error messages like "the stupid polack messed up again", and had one of Shakespeare's plays in its entirety linked on one of the maintenance web sites. The other guy consistently set up SQL accounts with "password" and sysadmin privileges (I've gotten it secured now, but it's causing quite a bit of havoc for some users). Crazy and stupid, respectively. Then we have a contractor (still with us, hopefully not much longer)...who is arrogant AND stupid (with coding, anyways...quite manipulative with the non-technical people who control his paycheck). He implements concepts and technologies that he does not understand in completely useless and excessively complicated ways. He also has a big problem with turnover of his underlings, resulting in even crappier code. The rest of us want to completely scrap his project because it's so bad (the aforementioned "acid trip code"). But you know what they say: "CONTRACTING: if you aren't part of the solution, there's good money to be made in prolonging the problem."
I am lazy: I make sure it works before it goes out, and I write it so the user can configure it to do what they need without having to bother me to do hard code changes, recompile, and redeploy. I've already got enough of that with existing code I've not yet had time to rewrite.
So, in short, if you are neither crazy nor stupid, your code probably won't suck that bad. Every time I'm skeptical of my own code, I just look at the code I am maintaining and replacing. I simply remind myself: mine actually works. I wrote them from start to finish, so the code is consistent. My boss can look at it and understand what it's doing with his experience with older languages and teething knowledge of
Re:Something to note about other people's opinions (Score:4, Interesting)
duplicate what the code says in another language (i.e. english).
Some of the time, that is correct. Most of the time, it isn't. But that's just in my field (financial software). There are two languages in use in the software I write and maintain: "code", and "business". It is vital, in my area, that code is commented well, to explain the business reasons behind the code. Small loops sometimes speak for themselves and don't need commenting. For example, a method called "getAllCashSecuritiesForAccount", if it contains only a simple loop, doesn't need commenting.
But because developers come in who don't have a financial background, and don't know their way around the system, comments in the code are essential. It helps them understand both the code they are looking at, and the business flow.
But the main reason for having clear, concise comments in the code is so that you don't have to read the code. For example (apologies for the VB):
The above comments are all aligned. They appear in the IDE in a different colour. They are written in plain English. They are clear and concise. If I am looking for a bug which involves the total value which has changed being wrong, then from scanning 3 lines, written in plain English, it is fairly clear where I should start my search. Yes, given a few more seconds, I can read through the whole code, and see what is being done. But it's quicker and easier to read 3 lines of English than 15-odd lines of code, which aren't aligned.
In fact, possibly the most useful aspect of comments like the above are to eliminate all the code you don't need to read.
You could argue, of course, that the above could be broken down into 3 seperate methods, all clearly named. But I think that's overkill. This is a simple method, doing three simple things. I ought to be able to read it all the way through without having to flip between three different methods, which exist only to save the developer taking the time to type some clear comments.
Lastly: yes, I am aware that the above code performs two seperate iterations of the same objects, and is terribly inefficient; it is for illustrative purposes only, and on no account should be treated with any seriousness
Re:Something to note about other people's opinions (Score:2, Interesting)
Yet another interesting feature I'd like in an IDE. Something similar to Excel's freeze panes but dynamic. So it fallows the start of the block, so at the top of the screen you'll have:
if (blah == run_some_crazy_spagetti) {
It would make my life so much easier. The closest think I've seen is emacs status bar that will show } // if (blah). I think it makes more sense for the user to look in the intuitive direction (up) for the help on what block they are in not, up and if they don't see it then down.
That's Not Good Code (Score:5, Interesting)
The biggest thing I see wrong with other people's code is not at the syntax level or to do with commenting. It's based on a misunderstanding of basic CS principles. An example is in order from last week...
In the codebase I work on, there's a module that analyzes documents and tags them, assigning different weights to each tag based on relevance. (Think of the way google works--it reads a web page and tags it with terms, then if you type in one of those terms while doing a search that document comes up--yes I know this isn't the way google actually works, save it. :-p ) At one point we send a list of tagged documents from one system to another, and this area was the source of many, many bugs. The responsible developer spent the better part of last week slaving on this code and every change seemed to introduce more bugs than it removed. Finally, I got involved to see what the problem was.
Here is one thing (out of many) that I found. After the docs arrive in the new system, each doc is supposed to be persisted along with the top 5 most relevant tags (the rest discarded). The code was written to create a Document, check a hash table that maps the doc to the number of tags it currently has, add a tag if that doc doesn't yet have five, then increment the value associated with that doc in the hash table. When I saw this, my head almost exploded. At some point, this developer thought it would be a good idea to create a hash table and keep this information, information which is available in the document itself (he could've just called doc.getTags().size() to see how many tags it currently had). Now he created this hash table and all his code was written to depend on it, so of course he had to write a lot of code to keep it in sync with the state of all these documents.
This sounds like a simple enough thing, right? It's not necessary, and it's not the best thing, but it's a fairly simple mistake and one that couldn't impact code readability all that much, right? Maybe--but consider that this is one of about 10 simple mistakes I found, and you can imagine the explosion of interactions of all these simple mistakes...and that's why we burned a person-week on something that should've been trivial. When I pointed out to this developer that he could just get the number of tags directly from the doc itself, and doesn't need to keep this state in some other object too, he said something to the effect of, "That's a different approach, but whatever...one's not better than the other."
But one is better. If this developer understood the difference between intrinsic and extrinsic, he never would've written that code in the first place much less defended it. To put a fine point on it: the number of tags associated with a document is intrinsic to the document itself, so that is where the information should live...not there as well as some hash table somewhere. The document is the authority and the final word on how many tags it has at any moment in time. (There's a principle in databases called the SUA Principle--it means one should keep data in a Single place, in an Unambiguous manner, and that should be the Authoritative source of that data and no other. It applies here too.) Putting this info into some other object, even if that object exists solely for the purpose of tracking that info, means you're creating an object that stores information that is extrinsic to it. Never a good idea...now you need a whole bunch of supporting code that keeps the extrinsic info in sync at all times.
Let's say I'm designing a Ball class for use in a physics application that students learning physics can use. They can shoot the ball out of a cannon, put it under water, in deep space, on Jupiter, etc, and see how the simulation behaves. As the developer of this class, I decide to add a characteristic to the ball that keeps info about its "heaviness". What should I add, a getWeight() method or a getMass() method? The developer I was talking t
Patterns dodn't work (Score:2, Interesting)
I don't think that's worked. If anything, they've just created more confusion and more ways to head down the wrong path. The more experienced developers merely call them "suggestions to consider", not a central bible of truth.
Re:My code is ok (Score:3, Interesting)
Nobody else but me takes any pleasure in good clean code, so I really shouldn't care much either. Honestly, there is very little business case for good clean code. You never see products that have "Now With 75% more clean code!" on their cover, do you? People dont pay money for that. They pay for "Now Solves 75% more Pain!". In other words, refactoring, rewriting, or optimizations are all cost centers that should be minimized. They do not directly add to a companies bottom line. New features do.
That isn't to say clean code is bad; create an unstable buggy app because your code sucks and you'll loose money. The trick is finding the minimal amount of "good clean code" you need to write to make your userbase happy. Anymore and you are wasting resources.
I'd argue if your paycheck is tied to some nebulous idea of "good code" is getting rewarded wrong. Your paycheck should depend on another, equally nebulous notion of "good user experience". I'd rather you write a nasty hack job that makes everybody smile when they use your application than a hard to use application that pisses everybody off, but has "good code" in it.
Good Code is code which creates a happy user. No other definition should be allowed.
Customer = Wrong (Score:3, Interesting)
The worst part is when the customer doesn't know what's best FOR THEM. Especially when it's your job to do what's best for them... then you have a contradiction. I work in advertising, and I run into this constantly. It's my job to help my clients sell their products/services, and they've hired me to do just that. But many times, clients think they know how to do it themselves, and then tell me what to do, when their ideas could, likely, harm their image and their sales.
What do I do? They've hired me to do my job and help them, but their very instructions will certainly harm them. My hands are tied, I just want to scream at them, "Let me do my job, and make you lots of money!"
Re:Something to note about other people's opinions (Score:3, Interesting)
Since we are nitpicking, I would say that I do not use hungarian notation. It assigns variable names based on their type; I assign variable names based on their expected usage and their scope. For example the m_ prefix tells me where to find the variable, rather than what it is. I would also use type prefixes in cases where they say something important about how the variable is used. For example, "m_pDocument" is a better name than "document" because it explicitly tells me that this object does not own the document, and that the variable is to be used with -> instead of