As @neodymium points out in a zenly fashion, don't let your algorithms drive the code. To exemplify what that actually means consider the following griefing contraption in C# that you've written a week ago:
public void DoArray(string[] strArr) {
string s = null;
for(int i = 0; i < strArr.Length; i++)
{
if(strArr[i].Equals("Needle"))
s = strArr[i];
}
if(s != null)
Console.WriteLine("I've found " + s);
}
It may take a while to find out what you've written just by looking at your code. But in the end you remember that this method looks for a "Needle" in the string array. You marvel at how ingenious your algorithm is but fret over the fact that it took you a minute or two to realize what it was doing.
Don't start making things clear by commenting!
Your first instinct may be to write comments to help your working fellows out, BUT STOP RIGHT THERE! Comments are nothing but an apology. Instead lets make ourselves clear in code… crystal clear.
In order to do that, try to think as if you've never seen your own code before. Force it by saying things to yourself like: "what is this" and "why is that". And then we'll start to refactor the thing. First simple refactor that we can do is to rename the method into something more fitting. How about:
public void FindNeedle(string[] strArr) { … }
What more can we do? We could:
- Rename
strArr
to something more appropriate, like haystack
.
- Change the return type to a
bool
and change the method so it'll return when the needle has been found.
- Move the
Console.WriteLine(…)
part of the method outside the context of this method so the calling code can do it instead like this: if ( FindNeedle(myArray) ) WriteFoundNeedle();
- Use
foreach
instead of for
.
The code may end up as following (your milage may vary):
public bool HasNeedle(string[] haystack) {
foreach(string straw in haystack)
{
if(straw.Equals("Needle"))
return true;
}
return false;
}
// Is called by the following:
if ( HasNeedle(strArr) )
{
Console.WriteLine("I've found the needle!");
}
Refactor in small steps
Lots of things can be done in order to make your code more clear, understandable and readable and this is achieved by refactoring your code. Do your refactorings in as small steps as possible. Like moving or encapsulating logic and naming them to something much more logical and readable. Something as simple as a long and convoluted if-statement:
if ( strArr[pos - 1].Equals("do") && strArr[pos + 1].Equals("then") )
… can be refactored into something simpler by moving the logic-statement into its own method:
if ( CurrentIsSurroundedByDoThen(strArr, pos) )
There are lots of ways to refactor. I suggest you read up some of them, Martin Fowler has written a book about it but there is also an on-line catalog available with code samples and/or class diagrams. Choosing what refactoring you should do or not has to be decided under the assumption that it will make your code more maintainable than before.
In addendum
Remember keep your refactorings simple and do it with SOLID principles in mind.
Also if you start out your project by writing unit tests the right way then refactoring becomes something much more natural. The more you refactor, the clearer your code will become.