Skip to main content

Problem Set 0 Notes

Here are some general comments that apply to many of the submissions.

  • Please do not check in .DS_Store. You can add it to your global gitignore or something.
  • Be wary of force unwraps: if you force unwrap a nil, it will crash the application. Imagine that the code you have written is a library, and there are people using your library. If they use your library and a crash occurs, the clients of your code will not be happy! Consider using constructs such as guard let and if let. We will talk more about this in lectures.
  • If you can do set with arbitrary data, having isSolved only check for emptyCells.isSolved is likely incorrect: I can possibly make all the values into 1, and it is definitely not solved. Of course it depends on how you define isSolved; in this case, I am defining it as "the current state of the Sudoku is correct".
  • Do not cram your methods without having vertical spacing. In other words, try to put more empty lines inside your methods to separate different sections of your methods.
  • Hide methods that serve as implementations by using the private keyword. For example, if you split the options method into three different methods on the row, col, and box, you might want to make these three methods private.
  • Related to the previous point: making properties open to external modification is not a good idea, as the clients of your code can modify them, breaking your representation invariants. For example, suppose you have the puzzle variable which is a 2D array of integers, representing your Sudoku puzzle. If you do not make it private, your clients can change them, and this can cause problems if, for example, you track your emptyCells variable separately by manually modifying them in the set method. You can utilise the private(set) keyword to make the variable getable, but not setable.
  • Some of you use a representation of 0 instead of nil in your Sudoku puzzle. First of all, if your set method still accept an Int?, this defeats the purpose of passing nil: you can just make it accept an Int, and pass 0 instead. Even if you change it, setting it to nil is the more semantically correct choice, as it indicates that there is nothing in the cell (which is exactly what is happening). Finally, if somehow you extend the puzzle so that 0 is a possible input, it would break the code.
  • Practice more defensive programming. For example, the set method might get a Cell(row: 100, col: 100), or it might set a cell's value to negative numbers. If you are not checking them beforehand, you might get invalid state in your puzzles. If you are using force unwrap, it might crash your client's application.
  • Related to the above, be sure to test these edge cases as well, and not just the normal use cases.
  • The Swift Array collection has many methods that can serve you well. For example, to check that the Sudoku puzzle do not break the property of the row uniqueness, it is likely that you can use the allSatisfy method on Array.
  • Some of you made some methods that are implementation details be non-private in order to test those methods. This is one way of doing it, but it is more preferable to test the behavior of the system instead of the internals. There are many articles written about it, see e.g. this one.
  • One thing that I have not yet seen is implementing SudokuSolver with the use of protocol extensions. In Swift, this is possibly the best way to implement the solve method: all objects that conform to Sudoku automatically gets the solve method!