Stable System Vs Better Design - optimization

In may Daily Job i come across this Dilemma :
"Stable System Vs Better Design"
In routine job when i am fixing some module, When i see bad design
-> Badly written code
-> Badly Written Algorithm
-> Optimization possible
I would prefer to fix these also along with issue i am fixing
But many people opposes my changes a few supports, People who opposes will say
"You should be business oriented if system is stable, If you change some thing may cause regression, Hence do not favor business"
some time :
you will see your own written code after 6 months, Always you will see some improvment opportunity in this
While who support will say:
This is continual improvement and system will be more stable
So i would like to know what you people think

If applicable, write a unit test (or several, to cover edge cases). This gives you the confidence to refactor and know that you haven't broken anything.
Of course, if the code is tightly coupled (or spaghetti!), that's going to be a problem.

If it ain't broken don't fix it - wrap it. Isolate the modules as much as you can without changing its implementation; they should be touched (fixed, improved) when / if a real need arises.

My opinion would be not to fix the old code if it looks not perfect unless the way it is written is interfering with your current task at hand.
Most of the code is written badly. It is a matter of fact. If you're not in a perfect team with the perfect understanding of quality value and the agreement on the approach to achieve and keep this quality level, your optimizations will not change the big picture. You may fix something now but the next guy will make the mess of the things again.

I have came to the conclusion that in this industry if its not broken, don't fix it unless there is a damn good reason to.

If you know the application inside out, or have comprehensive unit tests and time to test the application in a non-productive environment, go for it. Otherwise, do it just when it's necessary.

Both are correct and there is no easy way out.
If you don't fix problems as you encounter them, not all problems will be fixed.
If you break something with a fix that is not 100% related to the issue you're currently working on, then people will hate you.
On the other hand, if you fix some innocent code (or rather code that looks innocent) and it breaks in unexpected ways, you've found something valuable: Brittle code. Brittle code is usually something that no one dares to touch. But to make your product more stable, you must get rid of such code. The first step on this road is to find it.
I have to admit that such fixes cause a lot of "unnecessary" friction in the team. People will yell at you when you touch brittle code because they are afraid. Often, this code will blow into the face of your customers, so you will get heat from all kinds of directions.
So it really depends on how much pain you want to cause and what you're willing to endure. If you fix everything as you encounter it, the code will be better by the end of the year. But it often is worse by the end of the day.

I want to second all the "if it ain't broke, don't fix it" answers, but with a relevant link...
Things You Should Never Do, Part 1 - Joel Spolsky
In essence - sometimes that incomprehensible code is actually a necessary bugfix that you have no chance to understand.

On the one hand, changing code that's already more-or-less working can run the risk of breaking things, and it can easily become an all-consuming task.
On the other hand, leaving bad code alone for fear of breaking things can stifle new development, due to the burden of maintaining bad code.
Sometimes code looks bad because it has to deal with complicated corner cases, as Joel Spolsky points out, and rewriting it will create bugs by failing to cover those corner cases. Sometimes code looks bad because it really is bad, and rewriting it can fix bugs that you didn't even know were there. Experience with your code base should help you determine which code is which.
In Boy Scout Check-Ins, Jeff Moser discusses the idea of "always leaving the campground cleaner than you found it." Always leave the codebase cleaner than you found it, even if you can't fix everything; those little improvements add up over time.
As was said in this answer, unit tests are a good thing. Working Effectively with Legacy Code, by Michael Feathers, is a great resource on this topic.

I personally have a tendency to spend time fixing stuff rather than getting on with the required task. Unfortunately it is all too easy to start fixing what looks like an easy problem and unravelling a huge mess that you then wish you hadn't.
I have also worked with people who are the other way round, and can live with the bad bits as long as it gets the job done.
More often than not, you can spend ages 'getting something right' to make it easier to work with in the future and you'll find that code is never reused in the future.
I think the main thing is to have a balance of views on your team, discuss things regularly with others and ultimately, meet the requirements for your project, since it's the customer paying the bills.
Be constructive about any problems you find - don't just pick holes for the sake of it! Team code reviews help improve bad code over time as poor coders will start to understand how to make good code.
I would advise marking bad code with 'TODO' comments and then coming back to fix it later time/budget allows. At least you've got a flag for potential problem areas then, without having to (possibly) waste time on a fix that's not required there and then.

Related

When you write your code, do you deal with errors proactively or reactively?

In other words, do you spend time anticipating errors and writing code to get around these potential issues, or do you write the code as you see fit and then work through any errors on an issue by issue basis?
I've been thinking a lot about this lately and I'm very much a reactive person. I write my code, give it a whirl, go back correct error and repeat until application works as expected. However a friend of mine offered that he spends time thinking how each line is interpreted and fixes errors before they occur.
I must point out that re-active is pure PRE-live. I definitely make sure my application is working before it goes live.
There should always be a balance.
Too many error checking is slow and leads to garbage code. Not enough error checking makes your program crash on edge cases which is not very good to discover after having it shipped.
So you decide how reliable some piece of code should be and implement error checking accordingly. Some test utility can be not very reliable - less error checking. A COM server meant to be used by a third party search service in deep background should be super reliable - much more error checking.
I think asking this in isolation is kinda weird, and very subjective, however there are obviously a bunch of techniques that permit you to do each. I tend to use these two:
Test-driven development (this would seem to be proactive)
Strong, static typing (reactive, but part of a tight iterative development cycle, as in, it's enforced by my ML compiler, and I compile a lot)
Very occasionally I swerve into the world of formal verification of programs. That's definitely "reactive", but if you think a little more up-front, it tends to make the verification easier.
I must also say that I value a lot of up-front thought in programming. The easiest way to avoid bugs is to not write them in the first place. Sometimes it's inevitable, but often a little more time spent thinking about the problem can lead to better-quality solutions, and then the rest can be taken care of using the kinds of automated methods I talked about above.
I usually ask myself a bunch of what-ifs when coding, like
The user clicks the button, what if they didn't select a date?
The user is typing in the search box, what if they try to type html in there?
My label text depends on a value from a shared drive, what if it's not mapped?
and so on. By doing this I've found that when the application does go live, there are a ton fewer errors and I can focus on fixing more obscure bugs instead of correcting conditions that should have been in place to begin with.
I live by a simple principle when considering error-handling: garbage in, garbage out. If you don't want any garbage (e.g. invalid input) messing up your software, you have to find all the points in your software where it can get in and handle it. Of course, the more complicated your software is, the harder it is to find every point of entry, but I feel that the more you do up front the less reactive you will need to be later on.
I advocate the proactive approach.
I try to write the code in that style which results in maintainable and reliable code
I use the defensive programming techniques to prevent stupid errors in code due to my loss of attention and similar
I design the database model according to the fortress principle, SQL code checking for results after each singular operation
I think of potential problems that can happen with that part of the code and I account for that. Not for every possibility but for major ones I can think of right now.
This usually results in software operating rather smoothly. At times it even surprises me but that was the intended goal, so here we are.
IMHO, the word "Error" (or its loose synonym "bug") itself means that it is a program behavior that was not foreseen.
I usually try to design with all possible scenarios in mind. Of course, it is usually not possible to think of all possible cases. But thinking through and allowing for as many scenarios as possible is usually better than just getting something working as soon as possible. This saves a lot of time and effort debugging and redesigning the code. I often sit down with pen and paper for even the smallest of programing tasks before actually typing any code into my editor.
As I said, this will not eliminate all errors. For me it pays off many times over in terms of time spent debugging. Another benefit is that it results in a more solid and maintainable design with fewer bugfixing hacks and special cases added on later. But in any case, you will have to do a lot of debugging after the code is done.
This does not apply when all you want is a mockup or rapid prototype. Also practical constraints such as deadlines often makes a thorough evaluation difficult or impossible.
What kind of programming? It's impossible to answer this in any general way. (It's like asking "do you wear a helmet when playing?" -- well, playing what?)
At work, I'm working on a database-backed website. The requirements are strict, and if I don't anticipate how users will screw it up, I'm going to get a call at some odd hour of the day to fix it.
At home, I'm working on a program ... I don't even know what it'll do yet. I can't deal with 'errors' because I don't know what 'an error' is in this context, because I don't know what correct behavior is going to be. The entire purpose of the program can and frequently does change on a timescale of minutes to hours, so even a couple minutes spent thinking about errors this early is a complete waste of time. (It's even worse than browsing SO, since error-handling adds lines of code.)
I guess the only general answer is "I do what makes sense in terms of saving time in the long term", which is, after all, the whole reason to use machines to do work for us.

Is "You break it, you buy it" the best policy?

There is a subtle reason why it might not be good: Sometimes, the blame for breaking something really should be placed on the individual who wrote fragile code without automated tests, not the one who broke their code by making a should-be-unrelated change somewhere else.
One imaginable example is when someone programs against an interface in a way that assumes behavior specific to the implementation du jour, but not guaranteed by existing contracts. Then someone else makes a change to the implementation that fits in the contract, but breaks the depended-on code. No tests fail because no tests are written for the depended-on code. Who's really to blame?
The purpose of this isn't to blame people, but to understand responsibilities, and if "You break it, you buy it" is really such a good policy.
EDIT: I really worded this poorly. I meant it to be about how to write correct software with respect to dependencies, including hidden dependencies. I meant this to be a question of what a programmer's responsibility is to avoid bugs, not what to do when a surprise bug is found. BUT, since so many answers have been given already, I'll let the question stand as-is and indicate an answer accordingly.
I think you have nothing to gain and everything to lose by promoting an atmosphere of blaming and finger pointing. When something is broken, you should assign it to the best person to fix the problem, whether that is the last person to touch that area because he or she knows the area, or to the person who wrote it first so knows the design philosophy best, or even just the person without anything more pressing to do.
"You break it, you buy it" makes sense in terms of breaking builds, not more serious problems.
If you put the build into a state where it can't compile, or run basic tests, you are blocking other people's work. If you can't see a quick and simple fix (because you introduced a quick and simple bug) then just roll back your changes (perhaps with local copies of what you'd worked on in the meantime) and commit.
If the fact that you broke the build is ultimately due to a wider issue, then deal with that wider issue, whether by fixing it, reporting it, or assigning it.
Short term, the person who made the code-base unworkable quickly makes it workable again. Long term, the best person for the job (balancing different factors) does the job.
Fixing it is the purpose not laying the blame. Suppose the orginal author of the fragile code has moved on, who would own the problem? Suppose he or she is simply assigned to another project? The person who ran into the problem needs to be the one who owns it until it is fixed, he or she is the person currently there and currently assigned to the task of making changes to the application.
Now if you know the code was created with a problem that should be avoided in the future and the orginal developer is still there, it would be a good thing to let him or her know about the issue and why it caused a problem, but ultimately the person who ran into the problem is the one who will need to fix it to get his new code to work.
I would say that assigning ownership to the disaster prone may not always be the most productive strategy. It is likely its own reward.
The last person to touch it should be at fault, Refactoring is a large part of software development, if somebody touched the code and did not properly document, write and test the code than that is on them. As part of the estimate, the time to properly put the code in better shape than it was found should be included.
That being said, if something does not work, the whole team should take the fall.
In an environment where people have to work together, cooperation should be of greater importance than placing blame. If someone`s module is fragile and if his/her peers agree that something should be done about it, a good team-player would fix the problem; that is, he would write unit tests .etc
In any case, a programmer's own code is ultimately their responsibility, and if they can't handle the responsibility of making their code cooperate with that of others, then they rightfully must take the blame. But not before giving them a chance or two to clean up their act.

Respecting Fellow Developers [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 13 years ago.
Improve this question
We've all been there. You have written some code and unit tests, the tests all pass, and the code is decent (nothing's perfect, right?). Then, someone who is sure that they know better than you comes along and decides to change your code or the interfaces to your code just because he/she does not like the variable/class names that you used. No "real" refactorings, no real optimizations, no real improvement -- just different words -- not necessarily better words, just different.
My real problem with this is that (a) its a waste of time and (b) it shows a blatant disrespect for the fellow developer that wrote the code in the first place.
My visceral response is to lash out, but that's counter productive. Instead, I though that I might wright a paragraph or two as sort of a "Charter" or "Philosophy" that is adopted for the project. I'm wondering if anyone else has tried this, and if so, was it successful?
After looking at the initial comments below (which are appreciated), I think that my problem is primarily that this change broke the build for code that was already working. So time needed to be spent to fix the code for what was (in my opinion) a non value-added change.
-- Thanks
...decides to change your code or the
interfaces to your code just because
he/she does not like the
variable/class names that you used.
My real problem with this is that (a)
its a waste of time and (b) it shows a
blatant disrespect for the fellow
developer that wrote the code in the
first place.
My visceral response is to lash out...
I see some VERY CONCERNING things in those statements.
naming is REALLY, REALLY important. It is worth rewriting code to get it correct.
It is not YOUR code
How is it disrespectful?
You are taking it too personally.
I once worked with someone who freaked out when I made changes to "his" code. His code as horrible; it was buggy and unmaintainable. He was always staying late, fighting fires and breaking things - basically a negative contributor. I rewrote all his bad code for a big piece of functionality for a project one weekend and when he came back in on monday had a hissy fit. I am not saying your stuff is horrible, but maybe you need to calm down and be more objective about it.
Don't take it so personally. Step back and think about it - maybe "your" code needed fixing
We might be able to give better answers if you posted the code and changes, or at least some better idea of the situation with an example or two.
EDIT:
After seeing the code change and finding out that the build was broken, I am going to have to change the tone of this answer. I understand Steve's frustration - and i agree - that is not a good change. It makes a specific typedef more general and not very descriptive any more.
While I think some of my points are valid, in this case it looks like the changes were not appropriate.
The issue of code "ownership" is irrelevant. If the code changes are useless then everyone on the team should not be happy. If they are good changes then everyone should be happy about it. If there is a difference of opinion then you all need to find a common ground.
Breaking the build is not a good thing.
Steve, sorry if I came down harsh - it looks like in this instance you are justified in your frustration, but not because it is "your" code.
One thing that might help in this sort of situation is to require code reviews for all changes. People are less likely to make pointless changes if someone else has to review it first. If they can actually convince another developer that their change should go in then maybe it isn't so pointless after all.
Heey,
Guys! WE all need TO TALK!
Just sit together and TALK! There are always reasons to change and there are always reasons NOT to.
Decide together!
Don't just go to StackOverflow or a forum and say ask this kind of questions.
The new dev does it - he gets responses from community probably positive (yeahh, bad code should be refactored).
The current dev does it - he gets responses from the community too: "What an idiot could do such kind of changes!"
And the result is: Counterproductive, destructive, offensive environment for a long time.
Who wants it?
Just put your arguments on the table and that's it.
New dev needs some introduction too.
Old dev needs to listed TOO.
This should be collaborative work AND not pissing each other off.
Decide together, talk, as THE TEAM.
And... better ask questions like "How is it better to refactor this?"
Cheers.
In any software development team with a size > 1, standardization is key. Not only for each developer to understand the other's code, but so that the people that come along in 2 years, 5 years and 10 years can look at any part of the code and see a clear and consistent pattern. Will you... and the rest of the team... seriously still be there, working on this project, years down the line?
If you both "just have your way of doing things" and there is no formal standard for the project/company, I suggest you work with the team and/or your boss to suggest a formal standard be adopted. There are many standards already published for the various environments that you can use either as the standard, or as a starting point.
If there is a formal standard, everyone on the team is obligated to follow it... no matter how much "better" they think their way is.
So much for the hard skills.
Now on the soft skills side...
You and your colleague need to develop a healthy relationship, or decide to work in different places. Tit-for-tats that result in people feeling that they want to lash out will make everyone unhappy, not to mention gravely jeopardize the project everyone is being paid to complete. Look for a person you both respect (maybe your boss, maybe a respected and level-headed senior member of the team, maybe HR if you have a good HR department). Explain to that person what the problem is and that it makes you feel unvalued and disrespected. Ask for help talking through the situation with your colleague and agreeing to a better way of working together.
Finally, you need to be open to the possibility that your colleague may be making subjectively correct changes, even if the manner he's doing it in offends you. Separate the correct coding from the correct interpersonal interactions. Do the right thing for the project.
Well if that guy is going to maintain your code, let him do whatever he wants to.
Just remember that it is not "your" code. The code belongs to the company for which you work for. You wrote the code and you got paid for it. Let the Management do whatever they want to do with it.
Don't take things personally, move on.
Sometimes, changing names might be justified. It can be confusing if half the project refers to a person's sex, and then you check in some new code that refers to gender or something. Okay, this might be a bad example as technically they are two different things and their meaning is most likely still obvious. But if a project's code uses two different terms to refer to the same concept, it can be confusing.
Usually I try to leave people's code alone, unless I have some justification for refactoring. Luckily the same seems to go for my colleagues, so no, I have not had the need for writing such a charter yet.
How about using an automated build system, so when this person changes the code and breaks something the team will get an alert about it. This solves your problem with having to waste your time fixing something broken by someone elses change to your code. This way everyone will know that so and so made a change and broke the build, and can see for themself. The rule is "dont break the build".
You should be discussing this with the person who did it, in a non-threatening manner.
I believe every developer should take responsibility and hence own some of the code, but not all of the code. I understand the code that I've written better (irrespective of how good/bad it is) than any other guy that has ever seen it. Therefore the changes I make will be faster and less prone to error.
I don't mind anybody changing the code I've written later on, but I have a couple of conditions:
If you change the code and that causes something else to break, you are responsible for fixing it, not me.
If I don't agree with the changes you made I will change it back to the way I want it since I have to take responsibility for this piece of code in future.
Not all developers should be making changes to all the code, all the time. Only some of the time, for the purpose of getting to know the code (sharing knowledge).
I've never worked for an employer that endorses a "everyone can change anything any time" policy. Developers own certain parts of the code and they are asked specifically to make changes/refactor based on a development democracy.
You touch my code and break something, (1) you better have a good reason for the change that all developers agree with and (2) you better not leave broken things broken or ask me to go do the clean-up for you UNLESS you're my superior. I will humbly submit if that's the case.
I agree with Laurence that code reviews might help. This is an issue of how your team should work together. What might help is the notion of Egoless Programming - in a nutshell, considering the code as a joint product of the team, and trying to make decisions for the sake of the code rather than because of the programmer's ego. Your teammate violated the fourth commandment of egoless programming - "Don't rewrite code without consultation."
Maybe if your team is made aware of these principles, things will improve. I would try this.
Perhaps not completely on topic, but .... If you have developers who have the time to make changes to code just because they don't like the variable names used, then maybe the conversation should be about whether you have too many developers and which ones should be shown the door ... or how you're going to justify to management the bloated staff you have, especially in the current economic circumstances!

What OOP coding practices should you always make time for?

I tend to do a lot of projects on short deadlines and with lots of code that will never be used again, so there's always pressure/temptation to cut corners. One rule I always stick to is encapsulation/loose coupling, so I have lots of small classes rather than one giant God class. But what else should I never compromise on?
Update - thanks for the great response. Lots of people have suggested unit testing, but I don't think that's really appropriate to the kind of UI coding I do. Usability / User acceptance testing seems much important. To reiterate, I'm talking about the BARE MINIMUM of coding standards for impossible deadline projects.
Not OOP, but a practice that helps in both the short and long run is DRY, Don't Repeat Yourself. Don't use copy/paste inheritance.
Not a OOP practice, but common sense ;-).
If you are in a hurry, and have to write a hack. Always add a piece of comment with the reasons. So you can trace it back and make a good solution later.
If you never had the time to come back, you always have the comment so you know, why the solution was chosen at the moment.
Use Source control.
No matter how long it takes to set up (seconds..), it will always make your life easier! (still it's not OOP related).
Naming. Under pressure you'll write horrible code that you won't have time to document or even comment. Naming variables, methods and classes as explicitly as possible takes almost no additional time and will make the mess readable when you must fix it. From an OOP point of view, using nouns for classes and verbs for methods naturally helps encapsulation and modularity.
Unit tests - helps you sleep at night :-)
This is rather obvious (I hope), but at the very least I always make sure my public interface is as correct as possible. The internals of a class can always be refactored later on.
no public class with mutable public variables (struct-like).
Before you know it, you refer to this public variable all over your code, and the day you decide this field is a computed one and must have some logic in it... the refactoring gets messy.
If that day is before your release date, it gets messier.
Think about the people (may even be your future self) who have to read and understand the code at some point.
Application of the single responsibility principal. Effectively applying this principal generates a lot of positive externalities.
Like everyone else, not as much OOP practices, as much as practices for coding that apply to OOP.
Unit test, unit test, unit test. Defined unit tests have a habit of keeping people on task and not "wandering" aimlessly between objects.
Define and document all hierarchical information (namespaces, packages, folder structures, etc.) prior to writing production code. This helps to flesh out object relations and expose flaws in assumptions related to relationships of objects.
Define and document all applicable interfaces prior to writing production code. If done by a lead or an architect, this practice can additionally help keep more junior-level developers on task.
There are probably countless other "shoulds", but if I had to pick my top three, that would be the list.
Edit in response to comment:
This is precisely why you need to do these things up front. All of these sorts of practices make continued maintenance easier. As you assume more risk in the kickoff of a project, the more likely it is that you will spend more and more time maintaining the code. Granted, there is a larger upfront cost, but building on a solid foundation pays for itself. Is your obstacle lack of time (i.e. having to maintain other applications) or a decision from higher up? I have had to fight both of those fronts to be able to adopt these kinds of practices, and it isn't a pleasant situation to be in.
Of course everything should be Unit tested, well designed, commented, checked into source control and free of bugs. But life is not like that.
My personal ranking is this:
Use source control and actually write commit comments. This way you have a tiny bit of documentation should you ever wonder "what the heck did I think when I wrote this?"
Write clean code or document. Clean well-written code should need little documentation, as it's meaning can be grasped from reading it. Hacks are a lot different. Write why you did it, what you do and what you'd like to do if you had the time/knowledge/motivation/... to do it right
Unit Test. Yes it's down on number three. Not because it's unimportant but because it's useless if you don't have the other two at least halfway complete. Writing Unit tests is another level of documentation what you code should be doing (among others).
Refactor before you add something. This might sound like a typical "but we don't have time for it" point. But as with many of those points it usually saves more time than it costs. At least if you have at least some experience with it.
I'm aware that much of this has already been mentioned, but since it's a rather subjective matter, I wanted to add my ranking.
[insert boilerplate not-OOP specific caveat here]
Separation of concerns, unit tests, and that feeling that if something is too complex it's probably not conceptualised quite right yet.
UML sketching: this has clarified and saved any amount of wasted effort so many times. Pictures are great aren't they? :)
Really thinking about is-a's and has-a's. Getting this right first time is so important.
No matter how fast a company wants it, I pretty much always try to write code to the best of my ability.
I don't find it takes any longer and usually saves a lot of time, even in the short-term.
I've can't remember ever writing code and never looking at it again, I always make a few passes over it to test and debug it, and even in those few passes practices like refactoring to keep my code DRY, documentation (to some degree), separation of concerns and cohesion all seem to save time.
This includes crating many more small classes than most people (One concern per class, please) and often extracting initialization data into external files (or arrays) and writing little parsers for that data... Sometimes even writing little GUIs instead of editing data by hand.
Coding itself is pretty quick and easy, debugging crap someone wrote when they were "Under pressure" is what takes all the time!
At almost a year into my current project I finally set up an automated build that pushes any new commits to the test server, and man, I wish I had done that on day one. The biggest mistake I made early-on was going dark. With every feature, enhancement, bug-fix etc, I had a bad case of the "just one mores" before I would let anyone see the product, and it literally spiraled into a six month cycle. If every reasonable change had been automatically pushed out it would have been harder for me to hide, and I would have been more on-track with regard to the stakeholders' involvement.
Go back to code you wrote a few days/weeks ago and spend 20 minutes reviewing your own code. With the passage of time, you will be able to determine whether your "off-the-cuff" code is organized well enough for future maintenance efforts. While you're in there, look for refactoring and renaming opportunities.
I sometimes find that the name I chose for a function at the outset doesn't perfectly fit the function in its final form. With refactoring tools, you can easily change the name early before it goes into widespread use.
Just like everybody else has suggested these recommendations aren't specific to OOP:
Ensure that you comment your code and use sensibly named variables. If you ever have to look back upon the quick and dirty code you've written, you should be able to understand it easily. A general rule that I follow is; if you deleted all of the code and only had the comments left, you should still be able to understand the program flow.
Hacks usually tend to be convoluted and un-intuitive, so some good commenting is essential.
I'd also recommend that if you usually have to work to tight deadlines, get yourself a code library built up based upon your most common tasks. This will allow you to "join the dots" rather than reinvent the wheel each time you have a project.
Regards,
Docta
An actual OOP practice I always make time for is the Single Responsibility Principle, because it becomes so much harder to properly refactor the code later on when the project is "live".
By sticking to this principle I find that the code I write is easily re-used, replaced or rewritten if it fails to match the functional or non-functional requirements. When you end up with classes that have multiple responsibilities, some of them may fulfill the requirements, some may not, and the whole may be entirely unclear.
These kinds of classes are stressful to maintain because you are never sure what your "fix" will break.
For this special case (short deadlines and with lots of code that will never be used again) I suggest you to pay attention to embedding some script engine into your OOP code.
Learn to "refactor as-you-go". Mainly from an "extract method" standpoint. When you start to write a block of sequential code, take a few seconds to decide if this block could stand-alone as a reusable method and, if so, make that method immediately. I recommend it even for throw-away projects (especially if you can go back later and compile such methods into your personal toolbox API). It doesn't take long before you do it almost without thinking.
Hopefully you do this already and I'm preaching to the choir.

What are effective ways to log and track programming mistakes?

On occasion I've heard people discuss the benefits of keeping track of programming mistakes, if for no other reason than it increases awareness of common errors. I've started to keep a list of bugs that I find in my code, along with what could have led to them. The main question I have is this:
What information related to my mistakes should I be keeping
track of so that I can improve as a
programmer?
And a couple other questions related to this:
How do I use this information once I start logging my mistakes?
Is tracking mistakes truly beneficial?
This is only useful if you are actually vigilant with tracking and reviewing. When I was working on a team, no matter how much documented that for example our servers in the production environment were natted and would not be able to resolve their own domain names or public IP addresses, every 6 months, I'd get a call at 4 AM from the deployment team or dev team that a new developer was responsible for, and they either forgot or were unaware.
I remember a particular engineer who was repsonsible for deploying and he had paper checklists, we built him deployment tools that forced him to record his checklist, yet he would always forgot to set the connection string (resulting in the 4 am phone call). Point is it's only worth it if your going to use it vigilantly.
I've found the best way to use this is by implementing your rules into a code analyzer like fxcop.
I think what is more useful than keeping a log of individual mistakes is making sure you come away with a real understanding of why it was a mistake in the first place. Most mistakes stem from a lack of understanding about one thing or another, correct that understanding and you eliminate an entire set of potential mistakes in the future. If I would log anything it would be what I learned from the experience that I didn't know before, not the specifics of the mistake that was made which is likely to be of limited usefulness when you look back at it later.
what was the mistake
how can it be avoided
add the latter to an appropriate checklist, and refer to it as often as appropriate
I think tracking mistakes can be worthwhile, but in my experience it helps a lot to categorize them at some level.
Every programmer is going to make enough mistakes over the course of their career to fill an encyclopaedia. If you make a huge checklist out of all of them then you're never going to get any coding done because you'll eventually be spending all of your time going over your checklist. So: categorize your mistakes in some way that makes sense to you so you can rifle through your list looking at the most important mistakes for the sort of code you're currently working on.
Also, to add to the above as far as what to collect:
what are the symptoms of the mistake (so you can find it later)
how you actually solved it
Yes, tracking your personal mistakes is beneficial. Refer to the SEI for numerous data points (here's one at random). One such methodology is the Personal Software Process (PSP). It's too long to go into here, but here's a book about it. There's also this free SEI publication on PSP.
If you balk at SEI and think Agile is the way to go, you'll probably get better mileage out of a book like Clean Code: A Handbook of Agile Software Craftsmanship (publisher website).
Bottom line: disciplined developer = good, undisciplined developer = bad.
I would also want to ask the question of how much time would be required to accurately track the mistakes, and if that time could be better spent directly on improving the software instead. If you can do this in a minimal amount of time and are able to refer back to your records to prevent future mistakes, it may be valuable. In the long run though, I think it will be better to stick with an absolutely high level list of common mistakes you make.
I'd look for trends or similar types of errors that tend to recur. Once you're aware of the types of errors you make, you can be alert for them, or you can change your coding style to avoid them.
As an example, I worked very closely with my office-mate in a previous life. At one point I was halfway through my first sentence explaining some odd behavior, and he interrupted with, "increment your counter." I still double-check my loop counters today!
Instead of keeping a log of future mistakes, maybe you could review your bugtracker history, and try to find common types of errors which keep ocurring.
I'm so inspired I think I'll try this tommorow.
"What information related to my mistakes should I be keeping track of so that I can improve as a programmer?"
Read other people blogs. Write your own. You don't have to publish it. But you do have to turn each mistake into a story.
Don't drown this in metadata. This isn't amenable to a database or even a bug tracker. A mistake is a story where someone made a bad choice and recovered from it.
Here's your outline.
Context. What was going on.
Situation. The problem you were trying to solve.
What you did. Why it was bad.
What you should have done. Why it was better.
What changed. What you learned.
You should also record your successes in almost the same form.
Context. What was going on.
Situation. The problem you were trying to solve.
What you did. Why it was good.
What you learned.
When in doubt watch a movie. Seriously. Characters a confronted with choices, make mistakes and recover from those mistakes. That story line is the essence of drama. A mistake is the same thing.
Be careful what you log. Not every bad situation is a mistake. Some situations are inevitable or so far outside your control that nothing can be done about it.
Bad planning on someone else's part which puts you into panic-mode isn't your mistake. You can meticulously log everyone else's mistakes, but what's the point? If you're tracking what other people are doing, you should seek therapy.
Bad planning which provides inadequate budget, schedule or communication about changes may be a compound problem.
You didn't provide enough planning information up front.
In the scramble to cope, you made another mistake which lead to problem resolution and recovery.
In hindsight (which is always 20/20) you can see a decision which was wrong. However, at the time, it was based on best available information. That's not a mistake. Any sentence that begins "If we'd known that X..." is useless for mistake analysis. You can try to write a checklist of all the things you need to know next time you make that decision. But next time, you won't be making exactly that decision and some other piece of information will turn up missing.
Never call other people's actions mistakes.
Find the root causes. It's a root cause when it's something you can't control.
Don't retroactively call information that turned up missing a mistake.
I have been thinking the same thing. For the time being I keep a little spreadsheet with bugs I correct. The purpose of this is to make myself aware of the more common errors being made.
Hopefully I will start to see patterns and avoid making common errors over and over again.
I find that this makes my job more interesting, probably since I am an analytical person who likes to collect data and information in a structured manner.
You should try to relate the errors to use of inadequate tools, habits, methods or knowledge. In most cases you will find there would have been ways to catch the error earlier. Things like type-safety, unit-testing, code-review, coding standards, better API design, better documentation and working environment, comes to my mind.
I use JIRA with a custom workflow. For a bug, the last step before an issue is closed is a screen that allows me to select a "root cause". I've got a history of the root cause of every bug that's occurred in the last 3 systems I've built.