Long Refactoring: Generators

While the main solving function is now cleaned up, I am not very happy with the code that checks the validation on each cell.

I am not going to go through each step here, as the pattern is well established now. Pull out of the function anything that is a distractor. Once you have the heart of the algorithm, clean it up. Then put things back together.

Continue reading

Long Refactoring: Backtracking

Now that I have cleaned the loop up somewhat, we can continue with the process of refactoring the code. This is a continuation to the article series I started here.

This next step really moves beyond refactoring. I have identified that the intended backtracking was not actually implemented in the code. Instead, The whole board is wiped and restarted many times, causing a decent slowdown in execution. My refactoring process thus far has allowed me to understand the code well enough to attempt and improvement.

Continue reading

Long Refactoring: More loop cleanup

In my last article on the Long Refactoring series, I elided the process I went through to solve the bug. While preparing to turn the articles into a presentation, I went through the steps myself again, and came across the bug. When I was writing the articles, I was pressed for time, and didn’t go through the process of solving it step by step, which in turn means there is a gap between the pre-and-post states of the code: you can’t get there from here.
Let me take it from where I mentioned that I found a bug, and added the unit test that shows it.

Continue reading

Long Refactoring: Streamline the Algorithm

The code in tree_to_solution_string mixes the logic of solving the puzzle with the management of a linked list. Splitting your attention between these two levels can make it hard to track down errors. To continue teasing these two aspects apart, we need to make heavier use of the iterator. We’re in the middle of it now, and the code might actually feel like it is more of a mess than when we started. That is common, natural, and nothing to be afraid of.

Well, unless we get directed on to a different task tomorrow. Lets finish this up tonight.

Continue reading

Long Refactoring: Introduce Iterator

In a previous article, I had to shorten a bunch of lines that had a row and column value used as indexes to the board array. This repeated pattern is a call-to-action.

We want to encapsulate the logic for referring to a particular place on the board, and for advancing through the board. This is the responsibility of the Iterator pattern.

Spoiler Alert: we don’t get all the way there in this article.

Continue reading

Long Refactoring: Extract Method

This refactoring is my bread and butter. Functions tend to grow. Eventually, you need to split them. Find a section of the method that has its own self-containerd reason- for existence, and make that its own function.

I have in the back of my head that I want to extract a class that abstracts the boards from this code. I’ve been resisting the urge thus far, as keeping the board as a 2D array of cells is really conducive to sharing with other implementations of this code. However, the following refactoring should work to support either direction: pull out the code that constructs a board from the string. This has the added benefit of making it possible to write a unit test that calls tree_to_solution_string without having to parse all of the strings.

Continue reading

Long Refactoring: Extract Helpers

As the refactoring process continues, we will continue to decompose the large central class and functions. Right now, the SudokuSolver class is performing two functions. It is holding and managing the list of the puzzles, and it is solving them.

The heart of this code is the function tree_to_solution_string. Right now, I can’t call that by itself, as the SudokuSolver creates a bunch of helper objects before running through the whole set of tests. how can we tease this apart?

Continue reading