53

I've spent the last year as a one-man team developing a rich-client application (35,000+ LoC, for what it's worth). It's currently stable and in production. However, I know that my skills were rusty at the beginning of the project, so without a doubt there are major issues in the code. At this point, most of the issues are in architecture, structure, and interactions -- the easy problems, even architecture/design problems, have already been weeded out.

Unfortunately, I've spent so much time with this project that I'm having a hard time thinking outside of it -- approaching it from a new perspective to see the flaws deeply buried or inherent in the design.

How do I step outside my head and outside my code so I can get a fresh look and make it better?

8
  • 15
    In the future, please do not crosspost. If you made a mistake by posting to the wrong StackExchange site then flag for migration and explain where you feel it belongs and a moderator will migrate the question for you.
    – maple_shaft
    Sep 6, 2012 at 14:33
  • Ok, will do! :) A couple people had flagged to close, not move, so I deleted the entire question and brought it here.
    – BenCole
    Sep 6, 2012 at 14:34
  • Yup! - the people had clicked the 'close' button, not the 'flag' button (at least, I think that's what happened). From now on I'll flag it myself and wait for migration though.
    – BenCole
    Sep 6, 2012 at 14:42
  • youtube.com/watch?v=AtWjYTWGu6I Dec 21, 2012 at 18:11
  • IMO, If you can't find ways to improve things then you don't know enough. I have created some truly awesome designs in the past, but when I return to it a while later I always wonder why I would do something so stupidly. Anyways, you can take the approach that your design is just fine. Then when you add features, if it was hard, then figure out how you could have made it easy.
    – Dunk
    Dec 21, 2012 at 18:24

12 Answers 12

47

Ways to approach this:

  • Find someone familiar with the technology and business problem and talk it through. This may be hard in a single-person team but is generally the best option.
  • Work on a different project for a while. This also may be difficult but even taking a week's break can give you a fresh perspective.
  • Look at similar projects or products, such as open source products if any exist. Be careful not to copy code but they may have approached the idea completely differently.
  • Learn a new language, library or framework. The techniques involved may give you insight how to approach the same problems you have differently.
  • Read a good book/blog/magazine on design or the language/framework. I am not sure what level of skill you are at, but there are lots of alternatives in other answers on this site.

If you have specific examples you want addressed, perhaps post them here.

4
  • 6
    +1 learn a new language/framework. If you are working in a scripting language, learn an object-oriented one. If OO, learn a functional (lisp-ish) one. +1 read - especially data structures, design patterns, refactoring, and best practices. Read the Joel on Software books if you haven't already. I would also recommend user groups, and this site to keep exposing you to new ideas. If the ACM gives talks in your area, join and attend! Sep 6, 2012 at 15:14
  • 2
    More specifically to the languages, if you haven't learned it yet, learn Haskell, I thought everyone was exaggerating and being fanboys about how it will fundamentally change the way you approach programming problems. As a good scientist I put my hypothesis to the test by learning it, I was so wrong. You will approach your current design differently afterwards if you haven't already learned Haskell. Sep 6, 2012 at 15:36
  • 1
    Go to conference should be added here, IMO. Se my elaborated answer below.
    – Macke
    Dec 23, 2012 at 19:28
  • +1 for different project. Try something completely outside the scope of what you do day-to-day. You'll find a few parallels as well as a fresh architectural challenge.
    – Leniency
    Dec 24, 2012 at 1:04
13

Rubber duck debugging: Sit down with a piece of code or a module or a feature and explain it, out loud. When you find yourself saying something that sounds wrong, foolish, or just plain not right write it down as an issue to investigate.

9

Keep learning and expanding your skills. It's tough to know what you don't know, but when you see it, that "aha" moment will hit you. It could come from learning another language or design pattern.

You're going to be asked to make a change. You may find parts of your code that aren't so flexible and will require a lot of rework. This isn't necessarily a failure because you can't think of everything at first.

Users will start to complain. Just when you think everything is great...

7

A short memory helps. I've been known to complain about the "idiot" that changed something a week ago, only to find from source control it was me.

A good first step is to identify code that could be improved. Look in your source control for the files that change most often. Which code is the hardest to work with? Which code produces the most bugs? What kinds of changes cause a ripple effect throughout the code? At this stage, you don't have to know why the code is troublesome, just that it's troublesome.

Once you've identified areas to work on, then try to figure out what the problem actually is. There are books that take a systematic approach to categorizing design problems. Look at Martin Fowler's Refactoring, Herb Sutter's C++ Coding Standards, Robert Martin's Clean Code, etc. They have a bunch of "rules" that let you look at your code in an objective way.

Once you've identified what the problem likely is, then try out different ways to fix it. For example, if the rule you broke is "prefer composition over inheritance," then change it to composition and see how it feels.

Obviously, it can be helpful to have someone else look at the code, but it's not always as helpful as you might think, because you are much more familiar with the kinds of problems the code causes than anyone else, and the reasons behind the design. Learning some ways to objectively evaluate your own design will pay big dividends.

2
  • 3
    +10 for the honesty of the "idiot" comment. :)
    – Jennifer S
    Sep 6, 2012 at 15:42
  • 2
    Related to the "rules" based approach, running static analysis tools (e.g. lint for C, JsLint for JavaScript, Findbugs for Java, FxCop for .NET) can often give useful hints, and code metrics (e.g. cyclomatic complexity, LCOM4) can show you what parts of the code may be problematic. Of course, you should always use your brain and take the advice of such tools with a grain of salt. Sep 6, 2012 at 17:03
4

Have another person look at your code. If you can't find another person to look at it, write up a complete description of the interaction like you're going to show it to another person. The process of trying to explain your decisions to another person (even if its just for practice) can help you really think out WHY you're doing things a certain way and help you see any holes in your logic.

1
  • 3
    I find that explaining things even to a non-technical person is helpful. If I can make a non-programmer understand the design and satisfactorily explain why one might need a window-factory-factory-factory, then maybe it would be good to use a window-factory-factory-factory. Sep 7, 2012 at 4:52
4

I know this situation very well. When I get stuck that way I try to take different points of view on the project.

1.) User / customer point of view - use feedback

Unfortunately we are caught in our code in a way that we aren't able to see our own flaws because we use our applications the way we have coded them. Look at how people use it and try to figure out what the most intuitive user guidance would be. Play around with UI prototypes. This seems to be fun, but if you find out that you would be forced to recode huge parts of your code just by changing the usage logic than it's time to start a redesign cycle.

2.) Do a functional analysis of your code and visualize it

Some IDEs and frameworks push you to e.g. mixing UI and backend code. If you let this happen you will at some day face the situation that your code base can hardly be maintained because of nebulous and hard to break dependencies. Especially mixing UI code with other code can lead to spaghetti code and redundant functionality. Divide your code in functional blocks like e.g. database classes, communication classes, UI classes, core classes etc. and give the function blocks speaking names. Then visualize the functionality with a graphical tool (I use a mind mapping tool) in order to find out whether your structure is logical and modular enough that you can reuse huge code blocks for different projects and you are able to replace them with newer versions without big pain.

The best way to do this in my experience is to create a document that visualizes all dependencies between your classes and their calls from your code. The result is a visualization of your interface design. If this code map looks like a complete clusterf*** than it's time to act. If not happened yet you should think about a suitable naming convention that represents your code structure in a way you don't have to think about how to call it and what it does.

3.) Use common approaches to quality assurance

My favorite is the FMEA. In terms of coding this means not only to analyze what went wrong in the past but also think about what could go wrong. A pretty common example is a suddenly dropped network connection. After you have done this you can classify the error conditions by consequences like data loss, crash, wrong calculation and judge the impact on the user. If not done yet defining streamlined error and exception classes and routines can help you to keep your code clean and straight. The best way is to implement those in every new peace of code before even starting to write anything else. (Well, I'm guilty not always to follow this advice myself.)

In addition it helped me to generate and frequently update an "improvement proposal list" for my own code. (To be honest there's still a lot of code in my projects I'm definitely not proud of.) I also try to take the time to collect and have a look at best practice code from API documentations, developer conferences or developer magazines.

Until this point there's no need to touch your code. It's simply about getting aware what's going wrong and finding a way to define how to improve your code.

Finally some tips for daily work from an old fart. Try to avoid to bite more than you can eat. This leads to too much pressure for clean coding. You rarely get the time to do it right, but you will have to take the time to fix the flaws afterwards.

Nothing is as long-lasting as the provisional solution, but when it breaks it's often to late to fix it in time. Examples are nasty hacks or strange exceptions I used to get something to work despite e.g. a flaw in the underlying framework or OS. And then the flaw get's fixed or the new version simply drops the API…

If you are stuck and get forced to find a workaround than make comments and take notes which should be reviewed from time to time. Normally we get better and better because of learning something new. If you find a better way implement it as fast as you can. Otherwise you might find yourself coding the workaround for the workaround and the exception of the exception one day. (He who is without sin among you, let him throw the first byte at me.)

2

Don't sweat the small stuff.

Everyone could code better. We do things fast and then realize a couple of weeks after that it could have been done more efficiently. The point is that 90% of your code is probably good enough.

Look over your bug logs and find the routines that might be causing issues. As you find the bugs, you can also review the code and think about what might make the code more efficient. Most of the time, you'll realize that beyond fixing the bug itself, you won't be able to make a noticeable improvement, but sometimes, you'll realize that there's a better way to do something.

Talk to users and see where they are noticing issues, either UX or speed issues. Fix these issues, with an eye for trying to improve your code.

At some point, you will discover that your code has become too brittle and that there is simply no way to make the changes that you need to do. Then think about how you could have made the system more flexible, either via APIs or test driven development. In many cases, you'll discover that you can just start putting these APIs into the code, with not a huge amount of changes. In other cases, you'll realize that the effort of improving the code isn't worth it.

Incremental changes can be hard. The goal is to not entirely re-write the code base if you don't have to. Sure, you're a better programmer now than you were a year ago, but what you have must be working right now. 5 years from now, when a junior programmer complains to you about the legacy code they have to try to fix, just smile and nod, and don't admit that you wrote it.

1

Have you considered leaving and finding a company where you can be in a team? I feel very strongly that isolated or in a stagnant team, developers miss out on a lot the profession has to offer.

Peer reviews let someone who is already outside your head give your advice. Stack Exchange Code Review might be a good place to put some code that isn't particularly proprietary to your company out for review. It probably can't handle huge blocks, but many programs are made of a lot of simple code and some other code that is not simple and creates a lot of the problems. If you have an example of some code that is typical, but gets repeated and altered many places, it might also be a good review candidate. For example, if you format messages, don't ask to have all the message passing reviewed, just one fairly complex example message.

If you want to be more objective about your own code, I guess you could compare it to a coding standard, run static or dynamic code checkers on it, or if you are sparsely documented, adding comments might help.

There is a psychology of testing that makes it hard to test your own code but we certainly try our best to do so during unit test. Reading your own code can be a similar, or worse problem. Many fields use mentors, competitive judging, coaches, etc. Our does too if you count architects, system engineers, and testers. Customers with access to a bug reporting tool or customer support department will give you feedback from outside your head once the product is fielded. This is another great reason for Agile's approach of releasing early and often. You may be the sole developer in your company, but there are people affected by your code who can give you feedback about it from some angle.

0

"Is this a smaller issue than I think it is, or is this a problem experienced by others as well?"

Sheesh. Enough already. If the code's in production, bug-free and doing what it's supposed to do, architecture is unimportant. At least for now.

All of us hopefully learn as we go. I've written a lot of code that I was proud of at the time I wrote it, only to decide it was awful a year or two later. Right now I'm working on a multiyear project that's filled with incredibly crufty code, but the code works. I'm taking a very conservative approach to touching any of it.

And so should you. If you don't see any major architectural issues right now, after a year of work, I think it may be safe for you to assume, for now, that there are no important ones. This isn't bad craftsmanship. It's moving forward.

0

In addition to other answers, I'd recommend going to a developer conference.

This will expose you to a lot of topics and people that will make you think about your own app and workplace. Especially as they will talk about what works and not for then, and issues that come up. There's a big likelihood that there's some overlap with your app.

Preferably, take 3 days for this. I've found that to be long enough to get the necessary mental distance to my own work and look at it through the eyes of a larger community (so to speak), rather than my own.

Incidentally, this also applies to teams of people too, since groupthink can happen anywhere.

Finally, if you don't get approval for this, say once per year, change job.

-1
  • Practice design patterns and Best practices

  • Choose a framework, tools, packages etc based on your app requirements and needs - for this you need to read lot of etch blogs and find solutions for each individual tech problem

  • Create design/architecture draft and discuss with someone who is good at technical/architectural stuff. Improve this draft using feedback and comments. keep doing this till you achieve stable state.

  • Implement code such that everything that app need is configurable and maintainable

    re-architecture and reimplementing your project will definitely result app having better consistency, performance etc.

-1

I believe that 'kicking around' the concerns with a few smart people helps. There needs to be specific information. Is it s 24x7x365 website? LoB app? Where is it running or hosted?

Once you get into the core objectives and desired outcomes, others can help to focus and direct your attention. Your code might be the best code ever written for one specific task - or the worst. It really doesn't matter - how does that affect the desired goal?

Not the answer you're looking for? Browse other questions tagged or ask your own question.