Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Lately, I've been going through a pretty weird phase. I feel the need to write/rewrite all the tools I use ( text editors,IDE's,libraries/modules ) and I don't know why . Even though this can be seen as a good thing ( because I learn alot of things in the process , and my software design skills are improving constantly ) ,
the weirdest part is that I throw away all the code after I'm done, so I kinda work in vain. I'm never satisfied with the code I write. Have you been experimenting this too? How did you get over it?
It sounds like you're driven by one of a couple different possible "syndromes" (or maybe more than one).
Not invented here syndrome (NIHS). This is where nobody's code is good enough, or does things in the way you want them done. So you think you can do it better.
How Does It Work? Syndrome (HDIWS). This where you are fascinated by a program and want to understand how it works, so you basically get down to writing it yourself.
Biting off more than you can chew syndrome (BOMTYCCS). This is where you think "That can't be too hard to do, so i'll just write it myself then I know what it's doing". Then, you get partway done with it, enough to make it kind of work, and you realize that your code sucks and that you made too many compromises to get it done quickly, so you throw it away.
Too cheap to buy it so you figure you can build it cheaper syndrome (TCTBISYFYCBICS). The name speaks for itself. The problem is that you get partway done, then you realize you've fallin into #3 above and think your time is worth more than whatever it is.
I have suffered from all of these, and more.. (Like the classic "Need to create an acroynm for everything syndrome (NTCAAFES)" ;)
I do this all the time (well, except for the throwing away part). Personally, I started to do this early in my programming learning (when I was a student); it got the point where I would examine the Java core source code and if I didn't like it, I would make my own/extend it. It got to the point where the running class joke was that I was going to reinvent Java.
Personally, I never got over it... Instead I found new ways to use the to my benefit. For example, rather than simply reinventing things, I found that there were things that I wanted that were/are not available anywhere else, so I would make them for myself. My first such project was a chat program. Sure many existed, but this was the only one my teacher didn't know about (hehe). Sure learned a lot about networking protocols through it, but once it was "done", my first action was to send it to all my buddies and we would chat while the teacher was lecturing... Soon enough he found out about it and has since then forced all his students to turn their monitors off while he is talking, but it was fun while it lasted.
Since then, I have been continuing to come up with my own projects that are useful to me, have at least one aspect that I will need to learn along the way, and one or more aspects of there not being a current program that solves the problem for me for free.
So in all, I recommend that rather than trying to reinvent the IDE and then throwing your code away, try to find some project or problem that you would like to solve on your own and use again. I believe that dogfooding (using your own programs) is the best any programmer can hope to achieve.
Put whatever code you write in a website and make it open source.
Let others discuss the code and make it better.
This helps you to improve your coding skills while you are giving back to the community.
Later you will be amazed to find that your code got better than what it was when you left it.
I think the nature of us as programming species is to want to control everything. We're total control freaks. Everyone has tons of reasons not to trust someone else's work. Any given day at the office can be proof of that.
However, in general, you'll be wrong. Chances are that tool/library/IDE/whatever was developed by a team that put a lot more time in to it than you'll be able to. Sure, it has it's flaws from the outside, but by the time you're done with your version, you'll probably find that yours has a few flaws of it's own.
It's just something you have to come to terms with.
In hindsight, it's not an entirely bad habit. It takes you out of your normal programming area and gives you exposure to other problems. Ultimately you'll be more versatile for it. If you continue doing it from that perspective, and mix it in with real productivity, I think it's perfectly healthy.
I commend you on this. You wouldn't be a good coder if you didn't obsess about the perfection of your tools, and also wonder how they were made, so:
Don't waste too much time,
make sure you release whatever you can open source,
but I look at it like a Padawan building his/her own light saber. It has to be done.
If you are just duplicating your existing tools, there is little value. But if have an idea on how to make it better, even in just one way, its worth it.
This way at the end of it you'll have a slightly better tool and you won't just throw it away.
I went though a similar phase with tools, but then I got more interested in other topics like graphics and games.
I only write tools when it's going to save me time (or, of course, achieve more in the same time).
There's plenty enough application code to be written without wanting to write tools as well.
If you're doing it in your spare time, then each to his own, I guess, but I find that the need to make money from the code I write kinda focuses my mind on what's important.
We programmers are flow-junkies. We enjoy the mental states associated with problem-solving and progress toward solution. Sometimes, when the projects at work get bogged down -- for a variety of reasons -- its tempting to turn to side projects as a way to get the flow-fix.
This isn't necessarily bad, as long as you're sharpening your tools or learning something, and it doesn't take time away from other responsibilities (work or relational).
You opted for the red pill didn't you? Somebody should have told you NOT to do that.
The problem is that if you really really like computers, and you spend way too much of your life thinking about them, you get to this point where the entire random/irrational state of software development -- that arbitrarily complex working mess -- seems to be clearly far more convoluted than necessary, even if you don't know what necessary is yet.
There is underneath it all, a fabulously amazing tool just waiting to be set free. It teases you from time to time, hiding in various programs, embedded along with various bits of data. Tantalizing functionality, that if only you could find a real way to join it all together to make one big super-cool system, you could ...
It's that purely mathematical sense that computers could in fact be something wonderful, if only they didn't suck so much.
Now take the blue pill, and get back to work ...
It also sounds like you might be really dissatisfied with the other work you are doing. I find that when I'm not enjoying my job, I tend to find anything else to do, and will get especially fixated on things that I can excuse as not being time-wasters because they are, on the surface, productive. Things like going back and cleaning up code that was really a one-time only ad-hoc, rewriting what already works, and making my own "improvements" on tools. If I'm right, it makes sense that you would then throw it out/walk away/find something else because if you are only doing that to avoid doing other work.
I've experienced it sometimes. For example, when preparing HTML documents for publication, I felt compelled to write my own tool to do it just the way I want. It's natural to want to make the world better. If you feel that urge - I suggest you go for it.
I think this is probably a good thing, if it's not getting in the way of getting things done.
But don't chuck it, even if it's rubbish, put it on the net somewhere, and when somebody else tries to do the same thing they can see yours and at the very least avoid making the same mistakes.
Related
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
As a programmer I sometimes find myself in the position of being dealt a task which is utterly tedious and downright boring. This is not surprising, it would be odd if all aspects of programming were fantastically challenging and fun, but that doesn't change the fact that I wish I could live without these types of assignments.
For the most part, I manage to just power through by simply finishing the task as quickly as possible, but other times it's just not that easy. I find myself doing anything but finishing the boring assignment, taking on multiple other assignments if I have to, just so I get a reason for not finishing. This is of course affecting my professional life, as I'm constantly jumping from challenge to challenge, leaving a trail of unfinished blah behind me.
How do you cope with coders coma? Are there any tips on how to be more productive when it comes to finishing boring stuff?
I quite like Steve Pavlina's timeboxing method to get rid of tedious tasks. It applies whether you have boring code monkey work to be cracking on with or a pile of junk in the closet at home you need to sort through.
tl;dr of the link: Timeboxing means allocate a time slice, then work, cutting out what would put you behind. It is meant to get rid of the motivation for procrastination, by not making the tedious task take up more time than it is worth. Besides tedious tasks, timeboxing can be used to make a dent in something complicated enough that you don't know where to begin.
One thing that I do when I know I'm putting off doing something (either by doing other tasks or just slacking in general) is to write down a schedule on a piece of paper for what I'm going to do for that day. It sounds stupid, but try it. Just write down what you're going to do and in what time range. The feeling of crossing an item out on your list is great, but the feeling of throwing out that entire list is even better.
If the task is tedious because it is repetative, I write a program to do the task for me. ;-)
Pass it on to one of the Interns
I generally try to solve the problem in a new way. For example use something you've just learned. Obviously expects bug and longer development time, but at least it'll be still fun.
Or you can just hire some cheap programmers from the other end of the world to finish the job for you :)
Amp...lots and lots of Amp....a good sugar buzz is all the motivation I need sometimes...
Nobody mentioned the Pomodoro technique. Timebox 25 minutes where you want to be absolutely undisturbed, turn off email, phone, IM client, etc.
It's amazing how much you can actually get done when working only on one thing :)
More info on this page about the pomodoro technique
There's no one simple way. The worst thing to do is to start multitasking to avoid tackling the boring stuff. The best way by far is to just do it as soon as possible and as quickly as possible, to get it over with. This becomes a problem if the task is pretty huge, say a weeks or even months worth of work, since it's really difficult to motivate yourself to work with tedious crap day-in, day-out.
Then again, it's all part of the job. You could as well be working at a Kwik-e-mart or sweeping floors somewhere. Tedious tasks need to get done too, unfortunately and there's no quick and easy way out of it.
A). Try and do something new as part of the boring task. That could be writing it in a new language or using a different framework technology. Recently I tried scratch-writing a Restful-MVC framework into .NET 2.0 for example.
B). Split my time 50/50 with an interesting project, always deferring the interesting stuff to the afternoon (better to coincide the stimulating work with that lethargic mid-afternoon brain-fail cycle)
C). If you really just have to get through it, treat yourself with things outside of work so you don't get too depressed. Junk food, sleep, xbox time, whatever. Hopefully your partner is accommodating :)
I usually offer one of my daily prayers (salat) and after that I said to myself, "You not going home until you Finish that, Whatever the task, or for however long you need to stay at office."
Break the task into atomic pieces (as far as possible) and then follow ryeguy's advice of task lists. I like to use the 'Getting Things Done' approach (GTD), and just incorporate the pieces of that task into the rest of my work. Breaking it apart helps minimise the boredom and using a structured task methodology makes sure I still get it all done.
At the end of the crap task, reward yourself and use that as a driver for future tasks of the same ilk.
When I get like this, I think of what a Great man had to say: If not now, when? And I just do it. I find that waiting to get motivated to do things will get me nowhere. I also find that doing things, even when I don't want to, gets me motivated to keep going and to continue working on my project.
Break up the task into less-annoying chunks.
Occupy your brain as much as possible: if the task only requires 20% of your intellect, you can probably listen to CNN radio (in some other language that you've studied, for instance) in the background. If it requires your full concentration, listen to whatever music you can without getting distracted.
Avoid simple carbs (sugars especially). This is personal, but I find that they cause me to crash and need a nap. Which is good sometimes.
Fight with your husband/wife/friends/etc. beforehand. This will make it very hard to focus and then boring tasks are a godsend.
Many times, repetitive tasks are better coded than performed. I end up writing a huge amount of "code" in Excel/OpenOfficeSpreadsheetThinger (Excel writes Ruby, etc. perfectly :) and using global find and replace in Netbeans. This might take longer the first few times, but these are tools that you need to learn to use.
If it applies and is possible, I try to explore a technology or methodology to peek my interests. However, this is not always possible.
I too have also found that breaking some huge, boring, or daunting task into smaller, easier to swallow tasks works best.
I pour the green stuff from a glow stick into my Mountain Dew.
I don't get coder's coma. I get mismanaged paralysis, where I do nothing because I'm afraid that any move is wrong.
It may not be the answer people are looking for here, but I sometime write programs to automate these stuff!
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Should I prepare my code for possible/predicted future changes so that it's easier to make these changes even if I don't really know if these changes will be required anytime?
I am likely to get lynched for my opinion on this, but here I go.
While I have had this hammered into me over years of reading idealistic articles and sitting through far too many seminars and lectures categorically stating the nirvana like benefits of this, I too had similar questions in my mind. This line of thought can lead to massive over-engineering of the code, adding many man hours or more to design, development and testing estimates, increasing cost and overheads, when in reality this is not often the case. How many times have you actually reused your code or a library. If it is going to be used in many places, through numerous projects, then yes you should.
However, most of the time this is not the case. You will often find it more economical (in time and money) to only refactor your code for reuse and configurability when you actually know that you are going to use it again. The rest of the time the real benefits are lost.
This is not, I repeat NOT, an excuse to write sloppy, poorly designed, poorly documented code. This should be a fundamental that is so wholly ingrained in you that you could not break it, but writing a class for reuse is a waste most of the time as it will never get reused.
There are obvious exceptions to this. If you are writing third party libraries then obviously this is not the case and reuse and expansion should be key to your design. Certain other types of code should be obvious for reuse (Logging, Configuration etc.)
I asked a similar question here Code Reusability: Is it worth it It might help.
Within reason and certainly if its not much effort.
I don't think you can always apply this, as it can make you over-engineer everything and then it takes too long and you don't make much money. Consider how likely the client is to implement something, how much extra it will take to prepare for it now and how much time it will save later.
If it requires a lot of work, but makes sense to save money, you could raise it with the client.
I seem to be in disagreement with a lot of people here, who say always - but I've seen a lot of things where effort has been put into make future features easy to implement ... but they've never been implemented. If a client hasn't paid for the time spent making the feature easy to implement, that's money straight off your bottom line.
Edit: I think its relevant to point out that I'm coming from an agency environment. If you are working on code for yourself, you can probably predict future development with a greater level of certainty, and so its probably feasible to do this in more cases.
yagni.
http://en.wikipedia.org/wiki/YAGNI (*inserted by friendly editor :-) *)
fix the bugs in that horrenous code you're writing today.
refactor when the time comes.
If you work in a refactoring-friendly lanuguage I'd say NO. (In other languages I'm not sure)
You should make your code as loosley coupled as possible and keep things as simple as possible. Stay specific and dont generalize to unknown use cases.
This will make your code base prepared for the things the future will bring.
(And frankly, most anticipations of the future tend to be sufficiently off-mark not to warrant coding for it today)
Edit: It also depends on what you're doing. Designing apis for external users is not the same as developing a web app for your company
Yes -- by doing less.
You won't know what the future requirements for your code. The best preparation for the future is not to implement anything that's not needed right away, and have good unit-test coverage everything you do implement.
Scalability in your code is one thing you should always consider.
The more time you spent today in catering for scalable solutions, the less time you will spend in the future when actually expanding
Predicted or very likely changes - yes, generally it's good to have them in mind.
"Take anything that might ever happen in the universe into account" - no. You don't know what could happen, trying to cover for everything unknown is just over engineering.
Remember that most of you code will be changed/refactored. If you know that you will have to change your code within the next week, prepare it. But don't start making everything exchangeable and modular by default. Just because "maybe in the future" you shouldn't create a framework, if three lines of code do the job for now.
But think twice, if the system behind makes refactoring difficult (databases).
One thing I learned in my mere year of coding for the company I work for, everything you do, no matter how perfect you think it is will come back haunting you for an update or needs to be altered because client X suddenly decided not to like it.
Now I am making my code highly customizable so when that day comes to do some adjustments, it would be ready in no time and I can continue with my work.
In a word, yes.
In a few more words, you should always make your code as readable as possible, include comments, and always assume that at some time in the future, you will be called upon, or someone else will be, to modify the code.
If that someone in the future comes across a block of code, uncommented, unformatted, with no indication of what it does or should do, then they will curse you forever :)
No, never. Write good code that is easy to reuse/refactor but preparing for half thought out enhancements is, imo, the brother of premature optimisation; you'll likely end up doing things you don't need or that push you down a certain (possibly non-optimal) design path at a future date. As mfx says, do the minimum required now and unit test everything; it makes extending code a doddle.
In two words: yes, always.
What you describe is part and parcel of being a good developer.
See On Writing Maintainable Code
The obvious answer is YES. But the more important question is how!
Orthogonality, Reversibility, Flexible architecture, Decoupling, and Metaprogramming are some of the keywords that address this problem. Check out chapters 2 and 5 of "The Pragmatic Programmer"
I find it is generally a better strategy to design a "change-accommodating" architecture than trying to specify specific changes that might (or might not) happen. It is a good exercise, though, to ask "What may change in the future?", and then resist the temptation to prematurely implement potentially unnecessary features, but rather have such possibilities in mind when creating the application architecture.
I find that there is a parallel here to something I heard on test-driven development recently. The person talking about it had observed that while at first it could be a little annoying to always write unit tests and think about how your code can be written to be testable, it turned out that at some point it just begins to come naturally to write test friendly code.
The point is that if you always write with modifiability in mind, you might end up doing it more or less by reflex, thereby making the overhead of writing the extra code very small. If you can reach a state where high quality, extendable code is what comes naturally to you, I think that would definately be worth the initial cost. I do still believe, though, that you must to it in moderation and that sometimes it's just not the right thing to do for a given customer.
Two simple principles to follow:
KISS
Always avoid dependencies
Thats a good start
Yes, but only by writing maintainable, easily refactored code.
You should definitely NOT try to guess what might be required in the future. Such efforts are not only pointless and time-wasting for your current targets, but are more often than not counterproductive when any future changes become apparent.
This is really important. It needs to be done well, but takes experience.
If I count up the number of edits (via "diff") after implementing a typical requirements change, numbers like 10-50 are common.
If I make a mistake on any of them, I've inserted a bug.
So personally, I always try to design to keep that number down.
I also try to leave instructions in the code for how to make anticipated changes. If I'm maintaining code, I really appreciate it if the prior author also did this.
To balance the effort with the
benefits is the skill of design.
Not all our code needs to be flexible. Some things will not be changing.
No wasted effort. Finding the right parts to devote our attention to.
Tricky.
Yes, always think of where your code may need to evolve in the future. In the current project I am working on there are thousands of files and every single one of them has atleast one revision to it. Even leaving aside bug fixes plenty of those revisions are to make way for additional software features.
I wouldn't change my could to prepare for an unknown future feature.
But I would refactor to get the best solution to the current problem.
You can't design against an unknown (future), and as other people have said, trying to build a flexible design can easily lead to overengineering, so I think that the best pragmatic approach is think in terms of avoiding things that you know will make it harder for you to maintain your code in future. Every time that you make a design decision, just ask yourself whether you are making it harder to change things in future, and if so, what you are going to do to limit the problem.
Obvious things that will always cause problems:
Scattered configuration information - you need to be able to check and change this stuff easily
Untested code - you need tests to make changes with confidence
Mingling of storage and output concerns with the core logic - you will switch database instances and output formats, if only for testing
Complex architecture - you need to have a clear mental model of the system
Arrangements that require manual intervention or updates to keep them running
Setup
Have you ever had the experience of going into a piece of code to make a seemingly simple change and then realizing that you've just stepped into a wasteland that deserves some serious attention? This usually gets followed up with an official FREAK OUT moment, where the overwhelming feeling of rewriting everything in sight starts to creep up.
It's important to note that this bad code does not necessarily come from others as it may indeed be something we've written or contributed to in the past.
Problem
It's obvious that there is some serious code rot, horrible architecture, etc. that needs to be dealt with. The real problem, as it relates to this question, is that it's not the right time to rewrite the code. There could be many reasons for this:
Currently in the middle of a release cycle, therefore any changes should be minimal.
It's 2:00 AM in the morning, and the brain is starting to shut down.
It could have seemingly adverse affects on the schedule.
The rabbit hole could go much deeper than our eyes are able to see at this time.
etc...
Question
So how should we balance the duty of continuously improving the code, while also being a responsible developer? How do we refrain from contributing to the broken window theory, while also being aware of actions and the potential recklessness they may cause?
Update
Great answers! For the most part, there seems to be two schools of thought:
Don't resist the urge as it's a good one to have.
Don't give in to the temptation as it will burn you to the ground.
It would be interesting to know if more people feel any balance exists.
I'm a big fan of making lists!
As soon as the urge takes you to re-write something - spend 10 minutes making a list of the things that need re-writing. Follow all of the alleys that take you further into the code that needs attention and list those, too.
Hopefully within a relatively short space of time you'll have one of two things:
A really long list that completely puts you off wanting to rewrite anything ever again.
A list which actually isn't that long, so why not indulge yourself and go for a re-write?!
I've found that spending two months fixing bugs caused by my "harmless" re-write was enough to cure me of the urge to do these sorts of things without a clear mandate/project plan to do so.
The most memorable project of this kind for me occured some 4 years ago when I was called in to a remote office to "help" with a project that was due in 1 week for major presentation to the client and was not working yet at all. The project had been primarily off-shored to India, and IMO, a project management failure resulted in a ton of spaghetti code that was too fragmented to ever work properly in its current form.
After a full day's review, I presented my opinion to the management that the project simply needed wholesale refactoring and reorganization or it would never work properly. The result of this discussion was 6 days of 20 hours work / 4 hours sleep, 2 of which I actually spent sleeping on the couch in the company lobby due to the wasted time when driving back to the hotel.
The major improvements to the code included:
Application of naming standards
Moved into source control
Development of a build process
Documentation of the individual components
Most of the original code was left in place, but simply moved and reorganized / refactored to make it sustainable in the long term. Was it hell week? Sure. Did it make the project more successful? Yep.
I can't live with spaghetti code, and I'll often donate my own personal time to address it.
How to restrain one’s self from the overwhelming urge to rewrite everything?
Become old*
As this has happened to me, I've gradually lost the urge to rewrite everything. Why?
Once you've done it a few times, you realise that you often end up worse off than you started.
Even if you're god's gift to programming and your brilliant rewrite introduces no new bugs, you'll simply fail to notice or implement about 30% of the small edge-case features/bugs which things rely on. This will cost you months in fixing
Nothing wears down your irrational exuberance like time. Often this is a sad loss, but in this case, it's a win.
*(more experience may also be a suitable substitute if you lack the free time to become old)
The impulse to rewrite is righteous, provided that:
you "freeze" the existing code (with a label)
you start the rewrite attempt in a separate branch
you prepare first some unit-test in order to ascertain the current behavior and make sure you reproduce the existing features...
That said, you have to balance the rewriting process with the measure stability of the legacy code.
"If it is not broken, do not fix it" ;)
It's not quite an answer, but reading the beautiful article The Narcissism of Small Code Differences might help.
You're absolutely right that there's a right time and a wrong time to rewrite (and destabilize) the code.
Reminds me of an engineer I knew who had a habit of diving in and doing major rewriting whenever he felt like it. This drove the QA staff for his product up the wall -- if he report a bug about something trivial, the bug would get fixed, but the engineer's major rewrite of stuff he noticed while fixing the one bug would introduce fifty other new bugs, which then the QA staff needed to track down.
So one way to cure yourself of the temptation to do rewrites is to walk a mile in the shoes of the QA engineer who has to test, diagnose, and report all those new bugs. Maybe even lend yourself to the QA department for a few months to get a personal feel for the type of work they do (if you've never done that).
Another suggestion would be to make a rule for yourself to write up notes to describe any change. Perhaps post these notes when you check in code changes to source code control. You may be motivated to make the changes as minor as possible this way.
Just don't - The rabbit hole always goes too deep. Make any small local changes that leave the place cleaner than you found it, but leave big refactoring for when you're alert and have plenty of time to burn.
A nice starter on tackling big refactorings in small stages at sourcemaking.com :
you have to make like Hansel and
Gretel and nibble around the edges, a
little today, a little more tomorrow
reread "Refactoring".
Take a piece of paper and itemize the "Bad Smells" list.
(for each smell in BadSmells() {
print smell.name;
}
Add comments to the code including item(s) from the list.
while( odorPersists() ) {
Work through the list, laser-focused on one smell at a time.
}
Personally, this is where bug tracking software such as JIRA or Bugzilla come in to place with me.
I have a hard time NOT fixing all the broken windows when I see them, but if the situation is bad enough (and time permits) I will open a ticket and either assign it to me or assign it to the group responsible, that way I don't go off on a tangent.
-- I do only what needs to be done right them, but yet the issue is documented and will be fixed in time.
-- This is not to say that small broken windows should be handled this way; small issues should always be fixed on contact IMHO.
As far as I am concerned, if you have nothing better to do than to rewrite the code then you should make everyone else aware and just do it. Obviously, if it's going to take days to get any sort of result and the changes would mean excessive downtime then it's not a good idea, but eventually that code will become a problem. Make others aware that the code is awful and try to get some sort of movement to rewrite it.
The problem with the above statement is that as a programmer/developer you will ALWAYS have other things to keep yourself busy. Just leave it on the low-priority list of things-to-do, so when you're struggling with some work you can always keep your rhythm going with the rewrite.
Joel has an article about this:
There's a subtle reason that programmers always want to throw away the code and start over. The reason is that they think the old code is a mess. And here is the interesting observation: they are probably wrong.
I've never worked anywhere particularly agile, so what I do is:
1) Figure out whether there's a reasonable fix that doesn't involve major rewrite. If not, then clear some time (perhaps by explaining to others how difficult the fix is) and do the rewrite.
2) There is a reasonable fix without major rewrite. Apply the fix, run the tests, check it in, mark the bug as fixed.
3) Now, raise a new bug/issue (enhancement request), outlining the proposed rewrite and how it would improve the code (simpler? more maintainable? reduces coupling? affects performance or resource use?). Assign it to myself, CC anyone interested in that bit of code.
4) Give people a chance to comment, then prioritise that new bug within my existing tasks. This usually means don't do it now, because most of the time if I have one "proper" bug to fix, then I have at least two. Do it once the critical list is cleared, or next time I need to do something that isn't boring. Or maybe after a couple of days it won't seem worth doing any more, and it won't get done, and I've saved the time I would have spent doing it.
The important thing, I think, is to avoid shaving a yak every time you make a small bugfix.
The trade-off is that if the code you want to rewrite is really bad, then it's easy to under-prioritise the rewrite, and you end up spending so much time maintaining it that you don't have time to replace it with something that would require less maintenance. That needs to be borne in mind. But no matter what priority the rewrite should be, or how your organisation assigns those priorities, fixing bad design in the same area of code is not the same thing as correcting the out-by-one error that caused the crash you originally went in to deal with. This has to be considered at step 1: if the design means there are probably a whole bunch of other out-by-one errors lurking in the code, then just fixing this one is probably not "reasonable". If it really was a typo, but you happened to spot a refactor opportunity because you had the file open, then correcting it and touching nothing else is "reasonable".
Obviously the more agile your shop, the more significant a refactor you can do without it being so disruptive / time-consuming / political as to require a separate task.
If it's some code you've inherited, start making the code your own. Write unit-tests, then refactor.
Write more unit tests just to find out that the code is running perfectly fine.
If you still have the urge to rewrite it, you will have some tests to find out that your rewriten code is now failing ;)
Bad code is not something that can be avoided totally, but it can be isolated by proper abstraction. If it is indeed wasteland, which means, there is no landfills around, focusing design process is much more effective than trying to make people write perfect code.
IDon't think you SHOULD stop yourself from this. Mostly if you FEEL for the big rewrite it's mostly correct to do. I insanely disagree with Joel Spolsky on this thing...
Though it's one of few places where I disagree with him ... ;)
Stop rewriting when it is good enough. For this you need to know what good program is for you not only for your employer. After all you do programming for life not for good impression. Develop sound criteria which really would tell you that you are good and result is descent and it is time to go to next task. You should like your programs not less then your boss likes them.
Refactor only if your boss/company actually encourages it, otherwise you'll end up doing frequent extra time to bring up code to perfection... Until someone less dedicated touches it again.
Starting assumption: you already "commit early, commit often".
Then there's never a bad time to start a refactoring, because you can easily back out at any point. I find that at the beginning, it always feels like it's going to be easy, but after making a few changes and seeing the effects, I start to realise quite how big a job it's going to be. That is the time to ask whether there is really time to make the changes, or whether living with it until next time you come to this code is the better course.
The willingness to stop, throw away a half-refactored branch, and do it the nasty but quick way where appropriate, is key.
That's for refactoring, where the changes are incremental, and running (or nearly-running) software keeps you well grounded. Rewriting is different, because the time until you figure out it's going to take longer than you thought is so much greater. I may be taking the question too literally, but there's almost never a good time to throw it away and start again.
NB - This question is not a stab at RoR or at Redmine's plugin system
I have been working on a custom plugin for Redmine, a project manager platform built with Ruby on Rails (RoR). Now I am not really a RoR or for that matter, a Ruby guy. I have managed to write the plugin and everything works, despite being a mess behind the scenes. The "You're Doing It Wrong!!" feeling is coming from the fact that I know RoR is a highly-regarded framework, so there must be simple, better, elegant, [insert best-practice term here], ways of doing what I have done. I am not too concerned with making this code as perfect as possible, for the sole reason that this is only used internally, and really, people only care that it "works" (I am the only one who will look at the code).
What words of wisdom can be passed on to suppress the "You're Doing It Wrong!!" feeling? I am pretty sure if this feeling is present, then it is probably true that the task at hand is being done wrong.
What is the problem? The “You’re Doing It Wrong!!” feeling is the essence of our existence.
I read a piece of advice a while back that helps me in such situations. It can be paralyzing to try to do something the "right" way when you don't know anything about it.
So if I have to build, say, a customer-management application, my first step might be:
Build a really crappy customer-management application.
It's hard to build a good one, but it's easy to build a crappy one that does a thing or two. And while it's hard to know when something is good enough, it's pretty easy to know when something is crappy.
Once I have the crappy one in front of me, I can clearly see what needs improvement. And it's easy to change it, because the crappy one actually does something; so, using the TDD principle, I improve it while keeping it working. Eventually the crappy application evolves into a good one.
Many of the applications I've worked on that ended up crappy started out attempting not to be...and thus were overly complicated and hard to change, debug, and improve.
Don't suppress the feeling! That this is wrong feeling is the key to innovation. Just ask yourself "if this is wrong, then what would be better?"
Don't think of it as "You're doing it Wrong!!" Think of it as "What's a better way to do this?" Best case you end up doing it more efficiently, worst case you discover something that may be useful on your next project.
I have never finished a piece of code that I am 100% happy with. But then, I don't believe there is a single (non-trivial) piece of code in the World that can't be improved upon.
It is the developers who always think they have delivered great code that I worry about.
They say writers should write something every day, whether it's good or not.
Marc Raibert's advice is if you can't write something good, write something bad, and then polish the heck out of it.
My experience programming is when I've done something several times over, I finally start to get good at it.
So don't expect perfection.
RoR like a lot of other frameworks, make it really easy to do things that they anticipate, and quite difficult to do things that they didn't anticipate. This is true of almost all frameworks that aren't custom frameworks that you designed specifically for your project. The fact that you had to do a lot of messy stuff behind the scenes to do something doesn't surprise me at all. So, if you are doing something that wasn't anticipated, then it's perfectly natural to feel like you are doing it wrong, because from the eye of the framework designers, you shouldn't be doing that at all.
In many cases RoR employs 'syntactic vinegar' precisely to give you this feeling that there is a better way. You should probably look at some other plugins to get a feel for the conventions used. Generally if you follow the convention with RoR, it feels right.
Specifically with Redmine, the plugin system is still new and we are trying to work out the best practices. Since Redmine (and Ruby on Rails) are Open Source, I'd suggest bringing up your feelings to the project's forums and see what people think. Others might agree with you and can help to improve the systems.
Note: I'm one of the core developers of Redmine, helped build the Redmine plugin system, and have about a dozen Redmine plugins released. And even I feel things are backwards from time to time.
If you look back on any piece of code you write today a few years in the future, chances are you'd be shocked how bad it is. Put another way, it may show how much you've progressed over time. The feeling you are getting is part of continous learning. Start by getting it right and making it stable. Elegance comes with time, and fashion changes in computer programming style same as with everything else.
"What is the problem? The “You’re Doing It Wrong!!” feeling is the essence of our existence."
Perhaps not really related, but :
"A programmer is someone who makes a living out of solving the problems that were caused by the solutions he invented before."
The first time you work with a language, framework, etc, you're going to do something "wrong." As you develop other applications, or make tweaks & improvements to your original application, you'll find out what needs fixing, or what you could do better.
On every project, I almost always feel like I've done something sub-optimally, or not perfectly, but when it comes down to it, the code works, allows people to do what they need, and is in a way, a success.
So keep writing and keep learning!
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
Question
My question is how can you teach the methods and importance of tidying-up and refactoring code?
Background
I was recently working on a code review for a colleague. They had made some modifications to a long-gone colleagues work. During the new changes, my colleague had tried to refactor items but gave up as soon as they hit a crash or some other problem (rather than chasing the rabbit down the hole to find the root of the issue) and so reimplemented the problem code and built more on top of that. This left the code in a tangle of workarounds and magic numbers, so I sat down with them to go through refactoring it.
I tried to explain how I was identifying the places we could refactor and how each refactoring can often highlight new areas. For example, there were two variables that stored the same information - why? I guessed it was a workaround for a bigger issue so I took out one variable and chased the rabbit down the hole, discovering other problems as we went. This eventually led to finding a problem where we were looping over the same things several times. This was due in no small part to the use of arrays of magic number sizes that obfuscated what was being done - fixing the initial "double-variable" problem led to this discovery (and others).
As I went on this refactoring journey with my colleague, it was evident that she wasn't always able to grasp why we made certain changes and how we could be sure the new functionality matched the original, so I took the time to explain and prove each change by comparing with earlier versions and stepping through the changes on paper. I also explained, through examples, how to tell if a refactoring choice was a bad idea, when to choose comments instead of code changes, and how to select good variable names.
I felt that the process of sitting together to do this was worthwhile for both myself (I got to learn a bit more about how best to explain things to others) and my colleague (they got to understand more of our code and our coding practices) but, the experience led me to wonder if there was a better way to teach the refactoring process.
...and finally...
I understand that what does or does not need refactoring, and how to refactor it are very subjective so I want to steer clear of that discussion, but I am interested to learn how others would tackle the challenge of teaching this important skill, and if others here have had similar experiences and what they learned from them (either as the teacher or the student).
Like most programming, refactoring skill comes with practice and experience. It would be nice to think it can be taught, but it has to be learned - and there is a significant difference in the amount of learning that can be accomplished in different environments.
To answer your question, you can teach refactoring methods and good design in a pedagogical fashion, and that's fine. But, ultimately, you and I both know attaining a certain level is only through long hard experience.
I am not 100% to understand your question but I think you can refer yourself to Code Smell that need to be refactored.It contain a lot of example that you could show to other.
Here is a list of when refactoring should be used (list of code smell)
If you haven't read it, Martin Fowler has an excellent book on the subject called Refactoring: Improving the Design of Existing Code. He goes into substantial detail about how and why a specific piece of code should be refactored.
I hesitated to even mention it for fear that knowledge of this book is assumed by someone asking about refactoring, and that you would think, "Duh, I meant besides the Fowler book." But what the hey, there you go. :-)
You don't mention tests. To 'prove' that a refactoring does not break the existing functionality you need to either have existing tests or write tests before doing the refactoring.
Pair Programming seems to be the best way for me to get this across. This way, as we're working on real, production code, and we both encounter some code that doesn't smell right, we tackle a code refactoring together. The pair acts as the driver's conscience saying to do the right thing instead of the quick fix, and in turn, they both learn what good code looks like in the process.
Refactoring can be an art, and just takes practice. The more you do it, the better you get at it. Keep studying the methods described in Martin Fowler's Ractoring book, and use your tools (Resharper for Visual Studio folk)
One simple way to conceive of refactoring is right there in the name -- it's just like when you factor a common variable out of an equation:
xy + xz
becomes
x(y + z)
The x has been factored out. Refactoring code is the same thing, in that you're finding duplicate code or logic and factoring it out.
It sounds like your approach is a very good one. At the end of the process, you showed how you were able to uncover and fix a lot of problems. For educational purposes, it could then be interesting to invent a new change/enhancement/fix. You could then ask your mentoree how they would enact that change with the old a new codebase. Hopefully they'll see that it's much easier to make the new change with the refactored code (or how doing more refactoring would be the easiest way to prepare for the hypothetical change).
I see a couple of different ways you could try to teach refactoring:
Given textbook-like examples. A downside here is that you may have contrived or simplistic examples where why refactoring is useful doesn't necessarily shine through as well as in other cases.
Refactoring existing code. In this case you could take existing legacy code that you'd clean up, or your own code in development and show the before and after doing various bits to see how much better the after is, in terms of readability and ease of maintanence. This may be a better exercise to do as this is live code being improved and enhanced to some extent.
It isn't something that someone can pick up instantly, it takes time, practice, effort and patience as some refactorings may be done for personal preference rather than because the code runs optimally one way or another.
Teaching someone to refactor when they aren't a natural is a tough job. In my experience your best bet is to sit down with them in an office and refactor some code. While you are doing this keep up a "stream of consciousness" dialog. Talk about what you see, why the code doesn't smell right, options to refactor to, etc. Also you should make sure they're doing the same thing. The most important thing is to impart why, not how, to change the code. Any decent programmer can make a change and have it work, but it takes skill and experience to be able to state why the new solution is better than the previous.