188

I am a high school student working on a C# project with a friend of mine with about the same skill level as me. So far, we have written roughly 3,000 lines of code and 250 lines of test code in a span of 100 commits. Due to school, I put off the project for a few months and recently I was able to pick it back up again.

By the time I had picked it back up, I understood that the code I had written was poorly designed, such as inclusion of excessive threads in the renderer, poor prevention of race conditions in the interaction between the emulated CPU, GPU, and game cartridge, as well as code that is simply redundant and confusing.

The problem is that I have not finished even the main functionality of my program, so I cannot truly refactor, and I feel discouraged to go on perfectly aware that my code's design is flawed. At the same time, I do not want to abandon the project; a substantial amount of progress has been made and the work must not go to waste.

I feel as if I have a couple of choices: to simply finish the functionality by working around the poor design and then refactoring once everything is working, halting everything and working toward untangling everything before the rest of the functionality can be finished, starting the project all over so that it is fresh in my mind again, or downright abandoning the project due to its excessive size (essentially "back to the drawing board").

Based on others' experience in such projects, what is the recourse in getting myself back on the right track? From answers on this site, the general consensus is that rewriting is generally unnecessary but an available option if the code cannot be maintained without excessive cost. I genuinely would like to pursue this project, but as it stands, my code is not designed well enough for me to continue, and a feeling of despondency detracts me from continuing.

oldmud0
  • 1,573
  • 2
  • 10
  • 9
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackexchange.com/rooms/40914/discussion-on-question-by-oldmud0-a-large-part-of-my-code-has-a-major-design-fla). –  Jun 08 '16 at 22:40
  • 13
    Seriously: Having a major design flaw in his products never stopped Larry Ellison. Why let it bother you? – Pieter Geerkens Jun 09 '16 at 21:37
  • 54
    Work has not gone to waste. It has made you a better programmer. – sampathsris Jun 10 '16 at 04:40
  • 10
    This might not apply to you at the moment, but in the future if you write something you intend to professionally maintain, [don't ever do a big massive rewrite](http://www.joelonsoftware.com/articles/fog0000000069.html). – gcampbell Jun 10 '16 at 16:37
  • 1
    Instantly start over with no hesitation. 100% of software quickly becomes totally useless and has to be redone from scratch. What you're describing is just the normal course of events in software engineering. As soon as you see a better way to either refactor (on a small scale) or re-architect (on a large scale) just start that immediately. – Fattie Jun 10 '16 at 18:02
  • 8
    @JoeBlow "100% of software quickly becomes totally useless and has to be redone from scratch." This statement does not make logical sense. You're telling me the software I use everyday... is completely useless and has to be redone from scratch? – oldmud0 Jun 10 '16 at 19:32
  • 1
    Well - yes, of course. Nobody is using OS9 or Windows3. Software is remarkably temporary. – Fattie Jun 10 '16 at 19:52
  • Write more tests to complement your release 0.6 (minimum viable working code), so that when you do get to the re-write, it will be more like a refactor. – Philip Oakley Jun 10 '16 at 22:04
  • 2
    Working with awful codebases and turning them into good products is one of the best skills a developer can have. You are lucky that you have some code to practice with! – Daniel Jun 11 '16 at 07:02
  • @oldmud0 something else to bear in mind here. So yes - of course and obviously - totally rewrite everything. **So...**. Of course never try to "fix" software - everything from the hardware up is moving too fast; throw it out and do it properly (using whatever new language, API, or graphics card is briefly available this week) (until it changes next week.). **BUT...** Don't forget that perhaps the single guiding principal of software is that you break down tasks to units. (Indeed you do that fractally.) Consider: you should completely abandon *sections of* your system, one section at a time. – Fattie Jun 11 '16 at 12:39
  • 3
    Facebooks developer mantra: "done is better than perfect" – spuder Jun 11 '16 at 20:45
  • 1
    @JoeBlow Can you name a few large software projects that were successful after complete rewrites? Because the only examples I can think of that rewrote their whole software from scratch failed miserably.. which is no big surprise: Not releasing any new features or improving your application for at least 2 years gives your competitors plenty of time to catch up. Your second post (rewrite sections of the code) on the other hand sounds much more like *refactoring* code than *rewriting* which is certainly a good thing. – Voo Jun 12 '16 at 17:20
  • hi @voo "Can you name a few large software projects that were successful after complete rewrites?" OSX? (Is that big enough?) Any $100m+ thumbcandy game? All iOS products every time Apple happens to change languages? I do understand what you mean: these discussions can be confusing, because here you and I are discussing "whole products". (As in *"in year blah Adobe finally dumped all the legacy crap and rewrote Photoshop"* or whatever.) I apologize if I made the discussion unfocussed. Sticking to the topic at hand, OP and his 3000 lines of code. In short.... (cont) – Fattie Jun 12 '16 at 17:56
  • ... to quote the OP *"I understood that the code I had written was poorly designed [!], such as inclusion of excessive threads [!] in the renderer [!], poor prevention of race conditions [!] in the interaction between the emulated CPU, GPU, and game cartridge, as well as code that is simply redundant and confusing."* Those aren't "small errors you can improve", that's more like "a learning project where the OP is now vastly advanced in his understanding of the engineering involved." it's a dumpster fire, forget it and rewrite it. – Fattie Jun 12 '16 at 17:58
  • Perhaps one way to look at this - the OP has done some cowboy coding. That's like doodling, to get the project going. You don't "use", "refactor", "re-use" or any such process, code from your "doodling" stage. It's just doodling. – Fattie Jun 12 '16 at 18:05
  • @JoeBlow I wouldn't say candycrush and co qualify as a large code base, but Mac OS X is definitely a valid example. I understood your point more as a general argument than about this specific situation. I think everybody here agrees that a 3k LOC project is really a good learning experience and can be thrown away. – Voo Jun 12 '16 at 18:22
  • 10
    _"Well - yes, of course. Nobody is using OS9 or Windows3. Software is remarkably temporary."_ You are, as usual, mistaken despite your confidence! The Windows NT kernel, introduced in NT 3.1, is at the core of even Windows 10. Windows has not had a "complete rewrite" in some 20 years. – Lightness Races in Orbit Jun 12 '16 at 19:40
  • If you don't intend for your project to ever see the light of day, fine, rewrite. Otherwise: don't *ever* do a rewrite. Seriously. Made that mistake and it set me back a whole year. Read the article @gcampbell posted. You can always slowly refactor your code to fix bugs and make it more organized. – transistor1 Jun 13 '16 at 00:56
  • 1
    @LightnessRacesinOrbit that's true, but misses out the fact that "consumer" Windows - 95, 98, etc - had a very different kernel to the NT kernel, which was only used in the consumer versions from Vista onwards. – Rob Grant Jun 13 '16 at 11:38
  • 1
    10 start writing your code. 20 realize it could be written better. 30 GOTO 10. This loop never ends. – Agent_L Jun 13 '16 at 18:39
  • Is this the project you were looking to write 2 years ago with a collaborative IDE? – Aleksandr Dubinsky Jun 14 '16 at 08:23
  • @AleksandrDubinsky No, that one was for a school project. – oldmud0 Jun 14 '16 at 12:21
  • it'd be cool if you posted an answer on that question with kind of your conclusions end eventual opinion. a lot of people participate in questions like these and it'd be cool if they got closure (or, learn something). – Aleksandr Dubinsky Jun 15 '16 at 19:11
  • I can't help but notice that a lot of the answers feel the two options you were considering were, "continue with no refactoring" and "write everything from scratch." – Aleksandr Dubinsky Jun 15 '16 at 19:19
  • @JoeBlow I can't believe no one said this.. OSX is NOT a rewrite. Jobs brought NeXT with him. OSX and iOS still have NeXT code in them. ALL OS'es still have bSD code in them. Second OSX wasn't a rewrite of OS 9. A rewrite and a new product are different. A rewrite is a product which follows the same specifications as the previous product (in most cases). It's taking a working product, chucking the code, and building the exact same product again. OS X was based on NeXT anyways. Windows NT was based on Mica. Rewrite is different than "New Product." – Andrew T Finnell Nov 23 '16 at 17:20
  • Looks like my question became yet another example of the conundrum of being very high-voted, yet somehow considered not a good question for the site, because it had a dimension that turned out to be more debatable than I had anticipated. (And as usual, SE doesn't notify you when your question gets closed...) – oldmud0 May 22 '18 at 02:54

21 Answers21

275

If I were in your shoes, I would probably try it this way:

  • first, finish the current project - at least partially - as soon as possible, but in a working state. Probably you need to reduce your original goals, think about the minimum functionality you really need to see in "version 1.0".

  • then, and only then think about a rewrite from scratch (lets call this "version 2.0"). Maybe you can reuse some of the code from V1.0. Maybe after sleeping again over the situation you come to the decision you could refactor V1.0 and save most of it. But don't make this decision before you do not have a "proof of concept V1.0" at hand.

A working program "1.0" is something you can show to others, even when the code is bad (which noone else will bother about, except yourself). If in the middle of creating V2.0 you realise you are running out of time, you still have V1.0 as a partially success, which will much better for your morale. However, if you do not finish V1.0 first, there is a big chance you will never complete V2.0 because when you halfway through, there will be a point where you are unsatisfied with the design again, and then? Will you abandon V2.0 again and work on V3.0? There is a high risk of running into this never ending circle, never coming to an end.

Better take this as an opportunity to learn how to achieve intermediate goals, instead of an opportunity to learn how to leave projects in an unfinished state behind.

Doc Brown
  • 199,015
  • 33
  • 367
  • 565
  • 74
    One might also look at a working version 1.0 as an opportunity to learn about the refactoring process. – jpmc26 Jun 07 '16 at 05:19
  • 21
    This. I often find more than one bunch of design flaws / design constrains / requirements updates as I progress from nothing to 1st working prototype. Reaching an actual working state is important. – Eugene Ryabtsev Jun 07 '16 at 08:54
  • 14
    In my experience, bad design and/or development decisions usually come up as the project grows. As the answer suggests, it is for the best to have a working version 1.0 instead of restarting from scratch. You can then use this version 1.0 as a **baseline** for the next version. – Keale Jun 07 '16 at 09:10
  • 9
    Finishing a project will allow you to see potential problems that you have not yet encountered, and might actually show you that some things that you think are issues are maybe not as big as you think they are. Keep good notes and start designing a plan for 2.0 while you finish 1.0 – CaffeineAddiction Jun 08 '16 at 14:01
  • 2
    I want to make sock puppets to upvote this answer. Seriously, please please please finish your project. The only thing to add is that the project only really BEGINS when the coding is done. – corsiKa Jun 08 '16 at 15:58
  • 1
    @oldmud0, please allow me to emphasize that step 2 here is **rewrite**, not *untangling everything*. (1) Refactoring is integral to writing code, not something done only after the fact - "the quality goes in before the name goes on", an old TV commercial said. (2) The contrasting journeys of doing the same project "the wrong way" and then "the right way" will give you profound insights. It will permanently up your game. – radarbob Jun 08 '16 at 17:34
  • 2
    http://makegames.tumblr.com/post/1136623767/finishing-a-game may be worth reading; it supports the point of view in this answer. – stewbasic Jun 09 '16 at 06:28
  • 3
    A good point with "_A working program "1.0" is something you can show to others_". For example, with working code, you would be eligible to ask for help on [codereview.se]. – 200_success Jun 09 '16 at 17:39
  • 9
    The last sentence is amazing: `Better take this as an opportunity to learn how to achieve intermediate goals, instead of an opportunity to learn how to leave projects in an unfinished state behind.` – Brandon Jun 10 '16 at 18:41
  • 4
    I like this answer. I would emphasize that **you will continue to make mistakes** even during a rewrite. So its better to get to a functional project out the door. And by the time you reach 1.0 goal there will be _even more_ things to address that you can' t see at this point. – jmathew Jun 10 '16 at 20:50
  • One thing that helps me focus on finishing while feeling like this: write down your ideas for 2.0 as you think of them. Nagging thoughts nag because they get forgotten when not dealt with. Write the ideas down and get back to 1.0. – candied_orange May 21 '17 at 11:15
119

Finished IT projects, even faulty ones, are much better than unfinished ones.

Unfinished ones can teach you a lot too, but not as much as finished ones.

You may not see it now, but you get an enormous amount of value working with even faulty code.

My vote goes for finishing and then, maybe, refactoring - if needed. When you start working with more projects you will see that surprisingly often the part that "was meant to be refactored" stays untouched for years, while other pieces get extended.

From an employment point of view, in most cases, you will get more kudos for a finished project.

tymtam
  • 1,703
  • 2
  • 11
  • 11
  • 11
    Honestly, in non-trivial projects there are always a few bugs. List them and fix them in the next version. That's what release notes are for. – RedSonja Jun 08 '16 at 07:45
56

I would happily start the project over.

You're a student, and you're still learning. This puts you in a very different position than the question you linked to.

  • You have no professional responsibility for your code; if you were to delete the whole project right now and walk away, you would suffer no repercussions. This is a huge advantage for a developer. In the question you linked, those developers are trying to maintain software that people are paying money for, and even tiny bugs can cause big problems with customers, which makes it dangerous to write from scratch. You do not have that problem.

  • As a personal project, this is the perfect opportunity to try new things and learn from your mistakes. It's great that you recognize your old code has issues, because that means you've learned how to do better. Experience through trial-and-error can be invaluable for beginning programmers.

  • Your project is relatively small, and you basically have no tests. It could be as short a few nights to write 3000 lines from scratch, especially since you already have ideas about what to do better next time.

  • Working in a broken codebase will be a far bigger drain on your morale than a rewrite would.

As an aside, this may be a great chance to try writing a more modular program with unit tests. Doing so makes it much easier to understand the code if you come back to it after a long break, and helps to prevent errors you might accidentally introduce due to forgetfulness.

Finally, here is one opinion on the wisdom of sometimes taking steps backwards to take bigger steps forward.

Hylianpuffball
  • 677
  • 4
  • 3
  • 46
    Rewriting from scrarch is rarely learning from mistakes and is often simply making new ones – whatsisname Jun 07 '16 at 04:14
  • 28
    In my opinion, finishing a project is much more important then having the perfect project. The threat of a perpetual "it's not good enough" loop is real. – Pieter B Jun 07 '16 at 08:21
  • 9
    Sometimes when you're digging yourself a hole you need to stop digging; learn the lesson that's presented, and make the second version _simpler_. The second system mistake people make is to build it fancier and more complex. – Dale Johnson Jun 07 '16 at 09:15
  • 1
    With programming it is often easier and less messy to start a new hole versus trying to dig your way out of an old one. Keeping the old code just creates more technical debt. – Matthew Whited Jun 07 '16 at 16:40
  • @MatthewWhited: except it only seems that way, it often turns out not to be true. – whatsisname Jun 07 '16 at 19:12
  • 2
    I beg to differ. But that is why this question should probably be a community wiki instead. It is really easy to dig yourself a massive hold then tie everything in knots on the way to clean it up. Just taking a second pass on a new project can clean up many of those problems with the least effort. – Matthew Whited Jun 07 '16 at 19:15
  • 15
    It should be emphasized, people, that OP is working on a *toy project*. I've read Joel's [essay about rewriting from scratch](http://www.joelonsoftware.com/articles/fog0000000069.html), and none of his points are applicable to this case. OP is not selling their code to the real world, does not have a deadline, etc. Spending twice as much time programming means they learn twice as much. – Kevin Jun 08 '16 at 06:14
  • @Kevin, they only learn twice as much if they are doing deliberate practice, not just rehashing the same mistakes again. – whatsisname Jun 08 '16 at 17:23
  • 6
    @whatsisname They won't be making the same mistakes. As you said above, they will be making new ones, which will teach them new things. – Kevin Jun 08 '16 at 18:05
  • 2
    *"Working in a broken codebase will be a far bigger drain on your morale than a rewrite would."* - how can you tell? Got anything to back this up? – Simon Forsberg Jun 08 '16 at 19:01
  • Being still a student makes this the perfect time to learn good practices like "Don't rewrite unless you absolutely have to, and even then consider not." – corsiKa Jun 08 '16 at 19:09
  • 1
    This. I speak from experience. OP, I had a project in an intro to programming course. The code wasn't doing what it was supposed to, so I rewrote the program. I wrote one function for each task, making sure every piece of data the function needed access to was passed by the caller. – moonman239 Jun 09 '16 at 19:24
  • 4
    Exactly - it's a toy, show, or learning project. Instantly start over. – Fattie Jun 10 '16 at 18:03
33

You're probably still in the "learning fast" part of your development. There's a good chance that a few months from now, you'll find that your new and awesome design is horribly broken in ways you weren't even aware of when you started.

Get things done - this is the single most important thing you need to learn. Believe me, I know plenty of people (not just programmers) who are stuck in the "keep starting over from scratch since I've learned so much before I started on this project" loop. The problem is that it never ends - until you stop learning new things, which is not a nice place to be :)

It's also important for being able to actually finishing anything. Starting over is exciting, cool, fun... but if you only learn that, you'll never be able to finish anything. Again, that's not a very useful ability, and it actually doesn't feel quite as good as making something useful (or fun). Life is short, time is limited, and you can't just keep practicing with no tangible results - you'll go quite mad from that. If you find yourself unable to start working because you just can't decide which approach to take, you're already in the danger zone.

There will always be impulses to start over. Even in an learning environment, those are most likely a bad idea. That doesn't mean you need to carry every single prototype to a production-ready application, far from it. But you need to at least get to a working prototype phase - it will most likely help your morale, and it's a very useful trait for a developer of any kind. Get things done. And the fun part is, you'll quickly see that there's a million more fun or useful things you can do with your prototype rather than "rewriting it from scratch" - and in many cases, even refactoring it. Everything you do has a cost - at the very least, you could have been doing something else in the meantime.

Luaan
  • 1,850
  • 1
  • 13
  • 10
25

I follow the "Make it Work, Make it Right, Make it Fast" ideology in software development.

  1. Make it Work: Write the core functionality, so that the project is usable. Do what you have to in order to make everything work, even if it means ugly code.
  2. Make it Right: Fix bugs and refactor the code so that it is easier to read, understand, and maintain.
  3. Make it Fast: Optimize the program, aiming for a good balance between speed, resource usage, and maintainability.

Right now, you haven't finished step 1. Make it work first, and then you can worry about how ugly your code is. Actually creating a working product is one of the hardest things for new developers to do, because they get so wrapped up in trying to make their code perfect the first time around, and so they get stuck in Optimization Hell and never actually get around to finishing implementing all of the features. You have to learn how to put aside all those worries about refactoring and optimization so that you can just focus on making the software work. Once you get some more experience, you'll naturally do more things right the first time, so less refactoring is necessary.

Keep in mind: premature optimization is the root of all evil (see this excellent Programmers.SE question for a good discussion). If you spend too much time thinking about how to make your code better, you get stuck in analysis paralysis. This kills the project. It's better to just get the project done before you start trying to optimize it.

To quote a great motivational speaker: just do it.

As always, there's a relevant xkcd:

xkcd optimization

  • 1
    In open source, you can even insert step 0, "just make it". Even if it doesn't work, if it's interesting enough, release it, and maybe someone will help you with step 1. – Jörg W Mittag Jun 07 '16 at 14:28
  • 1
    Personally, I like right code. I even think right design may be more useful than problematic code. Regardless of the order of #1 and #2, I'm +1 because I like seeing the separation noted. If there are major implementation issues like checking for race conditions, such problems can often be fixed without needing to re-design the API (what functions call what), so you can bugfix by focusing on implementation details without needing to focus so much on on the functioning higher-level design stuff. So (potentially) there can be value in having the (semi?) working version of code. – TOOGAM Jun 09 '16 at 14:18
  • I don't think this applies. The OP is apparently talking about _fundamental design problems_. You can't safely "patch" those later. – Lightness Races in Orbit Jun 12 '16 at 19:43
  • 1
    Don't forget steps 0.5, 1.5, 2.5, and 3.5: make it readable. – candied_orange Jun 13 '16 at 06:07
23

Rewrite it. Non-working code has little value, and three thousand lines is not much code. It won't take nearly as long as it took to write the code you currently have, and it will be much better. I have often thrown out five hundred or a thousand lines of poor code, and often the rewrite is one-fifth as long.

Most of the notions around "don't rewrite" relate to large systems doing important things and undergoing constant changes to meet evolving requirements. Rewrites of complex systems in use rarely succeed.

Your situation is the complete opposite. You have a small application with no users and the only requirements are the ones you choose to implement. So go ahead and rewrite it.

kevin cline
  • 33,608
  • 3
  • 71
  • 142
  • 7
    If you are trying to follow an agile development cycle, the idea is that if you realise you have gone down the wrong rabbit hole, Throw it away and try a different direction, However if you have been using a source control svn/git you should be able to revert to a commit just before you went the wrong way so it will not be too big a change - if not, let this be the lesson to commit often. – Theresa Forster Jun 07 '16 at 07:38
  • 2
    At 3k lines of code it could take longer to check commits then to just rewrite the entire thing. – Matthew Whited Jun 07 '16 at 16:42
  • Regarding the git repo, just delete it and start over. The current code is almost certainly totally valueless. What reason to leave it on some server? - none. Click delete. – Fattie Jun 10 '16 at 18:05
  • 1
    @JoeBlow: no reason to delete the git repo. Just make a new branch. You never can tell when you might want to refer to old stuff. – kevin cline Jun 12 '16 at 19:41
19

Restarting from scratch is usually a bad move in real life projects, mainly because real life projects accumulate bug fixes that a newcoming developer is not aware of (e.g., see Things You Should Never Do, from Joel on Software blog.)

Neverthless, school projects don't inherit such history and usually start by coding and designing at the same time with partial knowledge of computing and lack of experience. I would consider your first version as a prototype, used as a proof of concept which has failed, and I would happily throw it away (see What are the differences between throwaway and evolutionary prototypes? for a discussion about throwaway vs. evolutionary prototyping.)

The right design has matured in your head and should not take much time to write it down in code.

mouviciel
  • 15,473
  • 1
  • 37
  • 64
12

I would respectfully disagree with suggestions that rewrite is a bad idea.

In the realm of software life cycle, it is generally accepted that the time and effort required to correct an error increases by an order of magnitude each layer in the life cycle. That is, if it takes 1 hour to correct an error at the requirements level, it will take 10 hours in design, 100 hours in coding-testing, and 1000 hours as a bug fix. Those numbers might sound outrageous, but they are industry accepted as being approximately correct. Obviously, less in a smaller project, but the general idea remains. If your project has a basic design flaw, then it is more appropriate to call that a learning experience and go back, review your initial requirements and redesign.

I would also encourage considering a Test Driven Development model using structured unit tests. They are a pain and initially seem like a waste of time, but their ability to uncover errors, especially when integrating with someone else's code cannot be over stated.

dlb
  • 225
  • 1
  • 5
10

You lost me at this sentence:

The problem is that I have not finished even the main functionality of my program, so I cannot truly refactor, and I feel discouraged to go on perfectly aware that my code's design is flawed.

I believe in the principle (stated in Systemantics) that

  • A complex system that works is invariably found to have evolved from a simple system that works.
  • A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over, beginning with a working simple system.

So, writing a complex system includes

  • Writing a simple system
  • Making sure it works

... i.e. the following steps:

  1. Write a bit of code
  2. Test it to make sure it works
  3. Write a bit more code
  4. Test again
  5. Etc.

Note that step 3 might involve:

  1. Write a bit more code
    1. Refactor existing code to prepare it for new addition
    2. Test the refactoring to ensure it still works
    3. Add the new functionality

Also, Step 2 "Test it to make sure it works" might involve some rewriting if it doesn't.

If I were building on a rotten code-base I'd be disinclined to add further functionality. So I'd be inclined to schedule something like "simplify the existing threading implementation" as the next piece-of-work to be implemented. Assuming that you have been testing as you go along, you ought to be able to treat this as a refactoring exercise. The success/exit criteria for this work-phase would be:

  • Source code is simpler
  • And no new bugs introduced
  • (And some old bugs eliminated)

Incidentally, "testing it to make sure it works" doesn't necessarily mean "unit tests" -- when the team structure is simple, you can test a (simple) system using (simple) system tests (instead unit tests).

ChrisW
  • 3,387
  • 2
  • 20
  • 27
7

One of the problems you are facing when running into a problem like this, is you are emotionally attached to the code you have written so far in some way or another.

A colleague told me he was writing a program while in university while he got lessons from a famous professor ( i believe it was Dijkstra). He asked the professor to have look at the code he had been working on for over a month. The professor asked him if he had made a backup, he replied no. The professor then deleted all of his code and told him to write it again.

He was pissed, but 3 days later he finished the program, with cleaner code and less bugs and less lines of code.

Try to make an honest estimate on what option is best in the time available for the project.

The 3 choices are

  • Delete it (completely, no looking back)
  • Continue working in the old design
  • Refactor code while you go.

I've been a professional programmer for over 10 years, and in my line of work I've come to conclude the last option is the most of the times the one chosen, but it is not always the best option.

Alfons
  • 181
  • 2
  • 3
    I once had a piece of code that had a bug. I had spent three days looking for the bug when my test fizzled and i succeded in deleting the code, no backups. I rewrote the entire codebase from memory in a all nighter an all my bugs were gone. About 3000 line codebase. So sometimes its worh it. But in production this never happens. – joojaa Jun 08 '16 at 12:19
6

It sounds like your skills have grown substantially in that time period. Perhaps working on that project contributed to it. Designing it again as a purposful learning experience would be fruitful.

Remember, this isn't something you need to deliver as a working program for a customer. It was written specifically for the practice. So, unless you want to practice having shipping issues and flawed delivery instead, I think you currently are in a developmental phase where working your "design muscles" would prove fruitful.

When doing so, focus on the design process and planning, and muse over your existing stuff and reflect on what you're understanding better.

JDługosz
  • 568
  • 2
  • 9
6

Refactor. Refactor. Refactor! REFACTOR!!!!

Honestly, no matter how experienced you are this is a common problem. You wrote code, you learned something, and you want to use the new knowledge on the old code. You want to measure the old code against the new knowledge.

That just won't work. If you do that your application/game will never be completed. Instead, try to allocate your time on the project so that some of your "tasks" are to refactor out the bad code. Let's say, for example, you had a horrible method of saving the game. Keep working on the game itself, but find some time to refactor (replace) that horrid method. Try to keep the refactors small, and it shouldn't be a problem.

When you get to a major part of the application that needs a refactor then you're doing it wrong, seriously. Break that refactoring down to smaller parts. Try to spend seven hours writing code, and one hour refactoring.

When you're done with the project and you hit feature freeze, then you can spend some massive time refactoring. For now, get the game done, but still try to refactor some. That's the best you can do.

There will always be something to refactor.

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
coteyr
  • 2,420
  • 1
  • 12
  • 14
4

I'd say it depends a bit on what kind of code you have now and where exactly the problems lie. I.e., if your foundations are good (proper class design in the most parts, good decoupling/cohesion etc., just a few bad choices like the threads you mentioned), then by all means get a bare-bones 1.0 out and then refactor like there's no tomorrow.

On the other hand, if it's really just a bunch of ugly slapped-together text files somehow passing the compiler, with no discernable structure etc. (in other words, a proof-of-concept learning-on-the-job prototype), then I'd rather delete it and start over.

On your next version, do an agile approach: set yourself a fixed repeating timeline, like 2 weeks or whatever fits your schedule. At the beginning of each chunk (let's call it a sprint), set yourself goals that are achievable in the 2 weeks. Go ahead and do them, try your damndest to make it work. Set your goals so that after each 2 weeks you have something that can be shown to a friend, not just some abstract internal work. Google "scrum" and "smart goal". This is all very easy to do, if you're alone, just a piece of paper with a few quickly jotted-down bullet points.

If you can do that, then starting over is good. If you know deep inside that after starting over you will likely end up where you are now, anyways, then stick with your code and make it work.

AnoE
  • 5,614
  • 1
  • 13
  • 17
3

You have to put yourself in the employers shoes.

To most recruiters, you'd be the most valuable if you go this way : - Finish it off with 100% tests on the new code you write. - Add tests for the old (bad designed) code. - Refactor it to achieve what you wanted as a design.

Do all that with a good versioning process, branches and tags.

Rewriting is often a sexy idea, but it's often an idea that newcomers have which is kinda dangerous in real life. Showing that you're more willing to improve the quality of work you already did rather that starting from scratch is a good sign that you're a serious person.

You can obviously rewrite it though, but make it another project then.

Steve Chamaillard
  • 1,691
  • 1
  • 11
  • 20
3

Just to add some of my past experience into the mix. I have been working on a side project for over a year now, whenever I get a spare few minutes. This project went from a simple testbed to a static class to a object orientated slim lined design it is at now.

Throughout all of these changes I have kept the same functionality of the code, excluding bug fixes and performance benefits (needs to be as fast as possible). The same code base although refactored has stayed the same and as such I have improved it massively without having to rewrite the code from scratch and waste time.

This has meant that I have been able to improve the code at a faster rate than I would have been able to before. It also meant as I was going it was easier to tell what needed to be removed, i.e. unnecessary classes, and what could stay easier than rewriting with the old idea still in my mind.

Therefore my advice would be to refactor your code and move on from there making improvements as necessary. Although do remember if you do decide to rewrite from scratch you should take the good ideas of the old project and look at them closely to see where they are flawed. I.e. don't just copy old code to the new project.

TheLethalCoder
  • 431
  • 2
  • 5
  • 10
3

The answer depends on something which I like to call the "complexity ceiling". As you add more and more to a codebase, there is a tendency for it to become more and more complex and less and less organized. At some point, you will hit a "complexity ceiling", at which point forward progress becomes very difficult. Rather than trying to keep moving by brute force, it is better to back up, reorganize/rewrite, and then continue moving forward.

So is your codebase so bad that you are nearing a complexity ceiling? If you sense that it is, take some time to clean up and simplify before proceeding. If the easiest way to clean up is to rewrite some parts, that is fine.

Alex D
  • 1,308
  • 9
  • 14
2

Neither? Both?

Continue onwards, spend some time on revising the existing design and some time adding new functionality.

If you have racy interactions, that might be a good place to start ("excessive threads in renderer" sounds like an inefficiency, rather than something that would cause correctness issues). See if you can figure out either a general way of getting away from races (and possibly deadlocks), or at least multiple specific ways of doing so.

I don't know to what extent things like deadlock and race detectors are available for C#, but if they exist, they may be useful in identifying what problems there are and verifying that your fixes are working.

I find that, in general, I'm more motivated to fix problems with code that does something useful, rather than throwing it away and starting, again, from scratch. There are cases where scorched-field (in analogy to greenfield and brownfield...) development is more satisfying, but that's usually for things where the existing approach is so way out from where it should be that it is no longer even wrong.

Vatine
  • 4,251
  • 21
  • 20
2

If your code is modular then you should be able to finish the rest of the code around the badly-written components then re-write the badly-written components without affecting the rest of the code.

In that case, it's up to you when you re-write the badly-written components. If the badly-written components are so badly written that the finished code won't work with them as they are, then you'll need to re-write them before you can finish the rest of the code.

micheal65536
  • 209
  • 1
  • 3
2

The first question you should ask yourself is "how bad is the flaw?"

What exactly did you do wrong?

If something is so bad that you will waste tons of hours trying to work with the issue, exposes sensitive data (passwords/credit-cards), or causes a bad vulnerability, then maybe you should edit it, but most of the time you can take what you have, finish it up, and fix the issue later.


Programmers love improving their applications, wanting them to be "the best that it can be," but that's not the correct approach.

IF you release your application as soon as possible, even if it's not 100%, bugs adn all, then you get FEEDBACK from others, while having time to fix the bugs and other stuff for version 1.1. Other people will be able to help you make the application so much better, and you might have wasted time doing something that people might have disliked.

So in your case, get it out there, get some feedback, and then you can structure version 2.0 with all the changes, and fixing the flaw you have.


Another thing to remember is that we are constantly improving. There is a saying that if you can look at your code from a year ago, and see that it's bad, that means you're still improving, and that's a great thing.

XaolingBao
  • 168
  • 7
1

It depends on how messed up your code is.

  • If you made real n00b errors which make your code overly complex or verbose, then I would recommend to rewrite those parts.

  • If you think you have serious bugs which you'll have to fix anyway, then write some unit tests that can check whether you've fixed the bug (...since you can't yet launch the program). It's better to fix bugs early, and it's definitely better to fix bugs while you still remember what the code does.

  • If you don't like what the methods are called, or which class they belong to, or little things like that, then just use the IDE. (Remember, this is C#, not some javascript, python, perl, php, etc.) When you're working on code that uses the affected component, and you have a clear picture in your head of what that component should be doing, then refactor it if your IDE makes it painless.

Otherwise, get it working and hone your skills on the next project.

1

As others have suggested, as this is a personal project, not (yet) a professional project, I would seriously consider a rewrite.

However, you can leverage the scientific method here, by performing an experiment. First, conceive a hypothesis. Mine would be, "it's probably time for a rewrite." In order to save time, reduce the cost of failure, and somewhat limit a priori bias, before you do any more programming, decide a length of time ("time box"). I would suggest perhaps 4 wall-clock hours. Also decide upon a methodology for evaluating the hypothesis. Since the stakes are low, I would suggest as a methodology, simply ask yourself: "am I glad I did this?" Now begin the experiment. After your chosen time box, what is the evaluation of the hypothesis? e.g. From my example, are you glad you started rewriting now that you have spent 4 hours doing it? Then it's probably the right choice.

You can ask for all the advice in the world, but there's nothing quite like testing out a hypothesis empirically.

A few reasons to consider a selecting a rewrite as your experiment:

  • In my experience, it's usually more fun. A big reason rewrites are often not selected in professional situations is that fun is far from the sole criterion. But you're still relatively new to coding, so fun is probably a pretty important criterion, and also an indicator of other factors that may be intangible for you at this early stage (fun suggests you will learn more, etc.).
  • Your experience and probably a nagging sense of conscience seem to be telling you that a rewrite is a worth considering. Listen that voice, if there is one. Even if you don't follow it's advice, at least listen. In the future there will be more external voices, and you need practice listening to your own good sense.
  • I suspect with a rewrite, you are more likely to modularize your code more. When you create modules, you have more reusable and reliable components you can leverage for other projects. You may even find that in the end, what seemed like a mere module of your main project turns out to be the most interesting and valuable piece of code you write.

Finishing something is a good idea, but not in a vacuum. If you begin a rewrite, then you could elect to finish something by finishing a particular sub-module. You could set that as a first goal, after the above experiment. Finishing doesn't have to mean finishing your initial main project just yet. After you finish a module, finish another, etc., until you finish rewriting the entire scope your original project, if you like.

Will
  • 712
  • 5
  • 12