- Programming problems and a method for solving them « Ballinger’s Professional Blog - [...] problems and a method for solving them Programming problems and a method for solving them « One Furious Llama.…
One of the things I’ve noticed about junior programmers is that they often feel overwhelmed by the programming problems thrown at them. This could very well be a situation of my own making I suppose, since I’m a big fan of throwing junior programmers into the deep end. Admittedly, it may, possibly, not always be the best way to learn for everybody but I’ve watched many beginners become very competent programmers very quickly by having to sweat, worry and solve difficult problems on their own. A little bit of stress never killed anybody… right?
The ability to learn quickly, on your own, is the single most useful characteristic a programmer can posses and I’m not sure if that ability can be tought, which is one good reason to start in the deep end. If you can learn to swim, you have that ability. Solving problems though, that’s an entirely different story.
Being thrown into the deep end is quite daunting and is supposed to be. Many new concepts and idea’s are flying around and often the confusion is so overwhelming and the problems seem so complicated that you don’t even know where to start, let alone how to solve the problem. Also, once you’ve dirtied your pants a bit, it’s really hard for you and the people around you to concentrate.
So, in the interest of a smell free productive work environment, here’s a method that I’ve used successfully on many projects, including ones where I’ve felt completely out of my depth, to solve problems quickly and efficiently.
I’m going to use a pretty straight forward programming problem I dealt with last year as an example. Obviously there was a bit more to it than this, but I’ve noticed few people have the attention span to finish re…
0. The problem
At a live event (a concert) there were going to be a bunch of girls walking around with Samsung mobile phones. They were going to be taking pictures of the people at the concert. These pictures would then be uploaded onto a mobi site for people to view on the web and the pictures would be also downloaded from the site back to the concert and displayed on the big screens next to the stage. There was a requirement from the sponsors of the event that all photo’s had to be branded with the three sponsors’ logo’s. To be fair, it was one of the more interesting projects I’ve done (it’s not often you get to code back stage at a live concert with bands all around you. Extreme coding baby, yea! But that’s another story.).
In this example we’re responsible for taking the uploaded photo’s and overlaying the sponsors’ branding on each photo. Working with images can be quite daunting if you’ve never done it before, but in reality the solution is pretty straight forward.
1. Understand the problem
Before you can solve a problem, you have to understand what the problem is. The better you understand every aspect of a problem the easier it will be to solve and the more effective your solution will be.
At this point in the process, you should really take the time to make sure you understand every aspect of the requirement as it will save you time and effort later. Don’t be afraid to spend time coming to grips with everything even if it feels like you’re wasting time. Hard to do with a manager or team lead breathing down your neck but trust me on this, of all the places, this is where you want to spend the time concentrating.
Even on a tight schedule it is worth it to spend time here since your solution will be affected by how you understand the problem and misunderstanding something may mean changing the solution later and the further down the line you get, the more costly changes become. Find every single problem you can think of (as well as the ones you can’t think of) straight off the bat because solving the overall problem will involve solving all the smaller issues that come up.
Developing any kind of system involves doing 90% of the work for 10% of the cases; you program for the exceptions. If there were no exceptions to the rule, odds are the system wouldn’t be required in the first place. And, seriously, no user is ever going to use the system the way they are meant to use the system.
In our example, the requirements are pretty straight forward. An image will be uploaded on a mobi site, this implies an HTTP post. The sponsors have logo’s which need to be put onto the image. The questions are:
In our example, there can’t be any human intervention, the process must be automated. This raises some interesting issues. We don’t know what the dimensions of the uploaded images will be. We don’t know if they will be landscape or portrait (they can be either). We don’t know what they will be of, what the colors will be or how much space we will have to place the logo’s.
There is really only one solutions to all those problems. The branding must not go onto the photo’s but rather the photo’s should be fit into a frame that contains the branding. In the real world a Polaroid like photo frame was chosen, with the branding at the bottom, so all we need to do is take a standard background image and overlay the uploaded photo onto it and save the new image somewhere.
In the end the solution was pretty simple but you have to understand the whole problem to be able to design a decent solution.
2. Document the steps of the solution
Now that you understand the problem, write out the steps of the solution. I usually use my own informal pseudocode to do this; what it looks like is not as important as understanding what you meant by it later. Writing (typing, really, since I am unable to read my own writing) out all of the steps of the solution helps to clarify the logic in your mind and adds to your understanding of the problem. It also helps to find holes in your logic. If you can’t write down the solution in simple terms, you will never be able to program the solution and there is nothing worse than coding something for 20 or 30 hours and then thinking “SHIT, I never thought of that” and then, in a pants browning panic thinking “and there is no hope in hell for me to rewrite this by the deadline”. It happens and that is where buggy sub standard software comes from (read: Windows ME).
In our example, you could start out with something like this:
Of those four basic steps, we’re most concerned with the merging of the images, so we expand that part, since it is the bit we need to program:
That already gives us a better idea of what is supposed to happen but it’s still pretty broad. We can expand that into something that more resembles a program:
Using that, you can ‘run’ the program in your head and any serious errors in logic should be self-evident. Don’t worry too much about the details of designing the most elegant solution; at this point, it should just work.
3. Break the solution up into manageable pieces
What I mean by ‘manageable pieces’ is: things, classes, pieces of code, functions that can be completed in a single working day. It can be one ‘function’ (merge two images method) or several ‘functions’ (a database access class) but you should preferably be able to complete each piece in one day. Obviously it’s not always possible or practical on every project but even large projects can be broken down into smaller pieces (like classes) and then again into smaller pieces (like class methods) until you get to a ‘manageable size’.
There are two reasons for doing this. The first reason is so that you can tell that you are making progress. If you set out to do something at the beginning of a day and at the end of the day you have accomplished that thing, you feel like you’ve made progress and you have made progress and that does wonders for your morale. If everybody on a team feel like they’ve accomplished something every day the project will go well. Or, failing that, at least every body on the team will have high morale.
The second reason is that you can show other people: team leaders, managers, clients, that you really are making progress. Being able to answer the questions “What are you working on”, “What did you do today” and “What are you going to do tomorrow” without having to think about it is not only good for your confidence in yourself, it’s also good for the confidence of other people in you.
Our example is too small to realistically break into smaller pieces, the whole thing should be done in much less than a day, so that will be our one and only piece. Ok, look, it should actually be done before your first tea break but I hope you get where I am trying to go with this…
4. Make a schedule
It doesn’t need to be a formal schedule or etched onto large stone tablets. You are basically putting down your intentions on ‘paper’ for yourself so that you have a concrete set of goals to work towards and so that you have a good understanding about how long it’s going to take you to do the work that you have.
Anybody who’s ever worked on a development project knows it’s very difficult to answer the “how long is that going to take you” questions and managers and clients just love to ask them. Being able to answer that question with confidence is not only useful to you but also to your manager and there is nothing better to a manager than a developer who always meets his own self-imposed deadlines.
Our example only has one piece, so our schedule is pretty short, but a longer schedule could look something like this:
Saturday? Just kidding, being a real programmer you will do the testing Friday night… right?
Don’t get too hung up on the schedule, things do change often, but also don’t ignore it. Setting realistic goals and then meeting those goals is what moves the project forward.
5. Review your pseudo code
Before you start coding, review every step of your pseudo code. Look for logic problems and look for ways to simplify the process – to make your solution more elegant. Your first solution may work just fine, but now that your subconscious has had some time to work over the solution, you may be able to spot ways of improving it that you didn’t consider before. This happens regularly, to me at least, when I follow this process. It is also much, much simpler to move around a couple of lines of pseudo code than to re-structure actual program code.
Before you start coding, go through your pseudo code again and make sure you fully understand your plan. Not only will it help you understand what you are about to code but once you start coding, it will astound anybody who happens to be watching you that you are able to lay down so much excellent code with so little effort in so little time…
6. Write some code
Basically, you’re just documenting your thought process at this point. Obviously, it is not possible to consider every single aspect and operation of your program in the design process (else there wouldn’t be a need to write the code now would there?); however, when you understand how to solve a problem, writing out the solution in code is much quicker, much more effective and vastly more bug free. And face it, there is nothing better than sitting down and laying down a vast amount of perfect code in once pass.
In my opinion, many programming bugs exist purely because of two things:
When you end up in scenario number 2, the complexity of the solution quickly runs away from you and when you no longer understand absolutely every aspect of what you’re doing the bugs will inevitably multiply.
It’s a Python script that takes two command line arguments, the image path and the background path. It then reads the image file, resizes it to the correct dimensions, pastes it into the background image and writes the merged file. It imports sys, os.path and Image.