Long Refactoring: Extract Read

The typical approach to Data handling is

  1. read
  2. munge
  3. write

We want out code to reflect that structure. In doing so, we make it much easier to adapt the code to read from different sources and write to different destinations.

In our last article, we split the display code off the data munging. Lets do the same for the code that reads in the puzzles from a file.

The initialization function starts like this:

class SudokuSolver:
    def __init__(self):
        self.board_strings = self.import_csv()

The import_csv file is self contained, and does not need to be a method of SudokuSolver. Lets’ move that outside the class.

diff --git a/treesudoku/tree_sudoku.py b/treesudoku/tree_sudoku.py
index 400450c..555ff27 100644
--- a/treesudoku/tree_sudoku.py
+++ b/treesudoku/tree_sudoku.py
@@ -14,9 +14,20 @@ BASIS = 3
 DIM = BASIS * BASIS
 MAX = DIM * DIM
 
+
+def import_csv():
+    list_of_boards = []
+    with open('sample_sudoku_board_inputs.csv', 'r') as file:
+        reader = csv.reader(file)
+        for row in reader:
+            list_of_boards.append(str(*row))
+    return list_of_boards
+    
+
+
 class SudokuSolver:
     def __init__(self):
-        self.board_strings = self.import_csv()
+        self.board_strings = import_csv()
         self.boards_dict = self.strings_to_board_dict(self.board_strings)
         self.box_index_table = self.fill_box_index_table()
         self.board_index_table = self.fill_board_index_table()
@@ -64,14 +75,6 @@ class SudokuSolver:
             return_string += str(current_node.value)
         return return_string
 
-    def import_csv(self):
-        list_of_boards = []
-        with open('sample_sudoku_board_inputs.csv', 'r') as file:
-            reader = csv.reader(file)
-            for row in reader:
-                list_of_boards.append(str(*row))
-        return list_of_boards
-    
     def strings_to_board_dict(self, board_strings):
         return_dict = {}
         for index, board in enumerate(board_strings):

We can now pass in the list of puzzles to the constructor. Note that to make this work we need to modify the test code as well. The constructor now looks like this:

class SudokuSolver:
-    def __init__(self):
-        self.board_strings = self.import_csv()
+    def __init__(self, board_strings):
+        self.board_strings = board_strings

And the calling code like this:

-solver = SudokuSolver()
+solver = SudokuSolver(import_csv())

The test code looks like this now:

--- a/treesudoku/test_tree_soduku.py
+++ b/treesudoku/test_tree_soduku.py
@@ -10,6 +10,6 @@ puzzles = {
 
 
 def test_sudoku_solver():
-    solver = tree_sudoku.SudokuSolver()
+    solver = tree_sudoku.SudokuSolver(tree_sudoku.import_csv())
     for key, solution in solver.solved_board_strings.items():
         assert solver.solved_board_strings[key] == puzzles[key]

Next up we will use a tool automate the style and safety of our code.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.