Clean Code

Reading

This week I read the first chapter of Clean Code by Robert C. Martin as well as the third chapter of Refactoring by Martin Fowler. I think these were optional, but I decided to take a bit more of a deep dive into these programming theories.

Clean Code: Chapter 1

The first chapter of Clean Code focused on our responsibility as programmers to write readable high quality code. This gives a very general overview of what clean code is, without providing very many specific examples. The chapter also highlights how detrimental bad code is for a project’s progress. Essentially fixing and refactoring code that doesn’t work well or make sense can take up a significant amount of development time. The chapter goes on to give several quotes from prominent programmers like Bjarne Stoustrup, Grady Booch, and Dave Thomas. Most of these quotes are also more general value statements about clean code than specific examples of how to write clean code. It is the first chapter after all.

Overall, I think the ideas of writing code in a way that works well and is readable are absolutely correct. I’ve had to read spaghetti code that I’ve written as well as other people’s, and its not fun. As I’ve grown as a programmer, I’ve tried to make my code as readable as possible. I try to make variable and function names descriptive, and I usually make it my goal to write code in a way that makes commenting my code unnecessary.

Refactoring: Chapter 3

Chapter 3 of Refactoring deals with the (terribly named) idea of code smells. I’m blown away that they chose this name, but upon researching found that the term was popularized in the 1990s which might explain it. Code smells are essentially vibes that pieces of code give you as to whether they are well written. This chapter lists many different code smell red flags such as duplicated code, large classes, long parameter lists, and switch statements.

This chapter’s information on how to refactor code was significantly more helpful with specific examples than the other book. This might be an unfair comparison because of this being a non introduction chapter. The authors even specifically mention heavily commented code being a bad smell, which I must have smelled myself while learning programming.

QNTM Blog: Counterpoint

I had to do some personal research on Clean Code to see some counterpoints, and I found an interesting blog post that goes over the book in a more critical way. This criticism of Clean Code first goes over some of the things that the blogger finds to be good advice. The blogger goes over the policies that the book outlines about functions. In the functions chapter, Clean Code explains that functions should be only 2 to 4 lines long. The blogger finds this to be an unrealistic limitation. The blogger also responds to some of the DRY (Don’t Repeat Yourself) aspects of clean code, and points out that today we have found that some duplication can actually be good for the performance of code. The biggest criticism throughout the blog post though is the subjective nature of what constitutes clean code and what doesn’t.

I found it really interesting to hear these criticisms and counter points, and it actually helped bring my understanding of the concept of clean code to a new level. I think its important as programmers to try to avoid falling into traps that are too dogmatic, as they can sometimes overcomplicate problems as well as create new ones.

Class Prompt

What is one thing from the articles that you would like to start doing (more often), and why? What is one thing you want to avoid doing and why?

The main thing I want to start doing with my code is thinking harder about the way I should structure the data before I start programming. There are times where I’ve gotten deep into programming a solution for an AdventOfCode problem, only to realize that if I had structured my data as a dictionary rather than an array, many of the pieces of the problem would have solved themselves. In terms of things I want to avoid doing, I want to avoid pushing through a problem and then abandoning the code I’ve written because it works. I think it is worthwhile to instead take a minute to refactor the code and follow the steps of Refactoring: Improving the Design of Existing Code.

In Practice

I decided to take a block of code from one of the first major programming projects I ever completed, and refactor it to be cleaner and give a better code smell. For background, the project was a battleship game where you play against an AI. I wrote the AI to randomly guess positions until it got a hit, and then make educated guesses in each of the cardinal directions.

function educatedGuess() {
    switch(direction) {
        case 'east':
            x = guessX + tries;
            y = guessY;
            if (onBoard(x, y) && isValid(playerBoard, x, y)) {
                checkHit(playerBoard, x, y);
        } else {
            changeDirection();
            educatedGuess();
        }
            break;
        case 'west':
            x = guessX - tries;
            y = guessY;
            if (onBoard(x, y) && isValid(playerBoard, x, y)) {
                checkHit(playerBoard, x, y);
            } else {
                changeDirection();
                educatedGuess();
            }
            break;
        case 'north':
            x = guessX
            y = guessY - tries;
            if (onBoard(x, y) && isValid(playerBoard, x, y)) {
                checkHit(playerBoard, x, y);
            } else {
                changeDirection();
                educatedGuess();
            }
            break;
        case 'south':
            x = guessX;
            y = guessY + tries;
            if (onBoard(x, y) && isValid(playerBoard, x, y)) {
                checkHit(playerBoard, x, y);
            } else {
                direction = 'east';
                tries = 0;
                randomGuess();
            }
            break;
        
    }
}

This is a very long function, and I can think of a few things I’d try now. For one thing, I think I would define the directions as x and y coordinates. For example: checking west of board position x, y could be seen as checking x-1, y. This would give us these results.

const directions = {
    North: [0, 1],
    East: [1, 0],
    South: [0, -1],
    West: [-1, 0]
};

I would then rewrite a guess function that would take the input of the direction and multiply it by tries.

function tryHit(x, y, direction, tries) {
    const [dx, dy] = directions[direction];
    const newX = x + dx * tries;
    const newY = y + dy * tries;
    return checkHit(newX, newY);
}

Our new educated guess function might look like this now

function educatedGuess(startX, startY) {
  let tries = 1;
  const directions = ["North", "East", "South", "West"];
  let directionIndex = 0;

  while (directionIndex < directions.length) {
    let direction = directions[directionIndex]
    if (tryHit(startX, startY, direction, tries)) {
      // Hit logic
    } else {
      // No hit thus direction change
    }
  }
}

This seems like an ok place to stop, as I see many changes I could continue making to improve my code. For instance, the naming conventions aren’t great right now as I have tryHit and checkHit and they do different things but sound exactly the same.

Conclusion

Refactoring code to make it cleaner takes a fair amount of work. It seems that writing code with these things in mind at the beginning would probably save a lot of time and headaches. I also still believe that periodically rewriting and refactoring code while you’re in the middle of a project is a good idea. The idea of clean code might be abstract, but I think that even being mindful of your code is an improvement.

Its rather fascinating seeing code I wrote 7 years ago with fresh eyes. I imagine I could refactor almost every line of this project. I’ve toyed with the idea of rewriting it in a purely functional way as well as rewriting it in an object oriented way. If you’re interested in trying this kind of buggy game I wrote all that time ago, check it out here. Its worth noting that you might have to resize your browser window until the menu for the placement of your ships shows up. You then have to click on the type of ship, the direction you want it, and the bottom board to place your ship. You really don’t have to play it but I wouldn’t want you to be too lost and I was too new to put instructions anywhere or fix the problems.

Print Friendly, PDF & Email

Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *