-
-
Notifications
You must be signed in to change notification settings - Fork 36
Outside-In with Aruba/RSpec for SudokuValidator Exercise #8
base: master
Are you sure you want to change the base?
Conversation
… inside the spec files. Also left a load of comments in to show my ideas of how I might express the errors.
…le. Be clear to use numbers, not strings.
…trix inside Puzzle.
…red specs into single Unit spec. Added new Box object that also is a Unit.
…dokuValidator stub, as the Puzzle is now aware of its own validity.
…cs to make the code easier to read.
…new Validator class. Previous scenarios green, but new steps failing.
…. Basic implementation, needs refactoring.
…tead of an array.
…command line tool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if Sudoku::FileParser#parse_rows returned a Sudoku::Puzzle object rather than an array of arrays? That would eliminate this intermediate state. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I like that. At the time I was thinking along the lines of, "What if we needed a Sudoku::JSONParser?" and so thought I needed a common format between the parser and the Puzzle, but you're right – any object that implements the 'Parser' interface/role could always return a Puzzle object.
In terms of testing this with RSpec, would you use expect_any_instance_of(Sudoku::Puzzle).to receive(:new)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danscotton I agree, all of the parsers could return Puzzle instances.
As far as testing, I would probably do something like expect(parser.parse).to eq my_puzzle. This will work because you re-defined Puzzle#== to check for value rather than identity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, thanks. If my Puzzle object wasn't a value object, would you go down the any_instance_of route then? I'm sure I've read something from thoughtbot about that being a bit of a smell but I'm not sure. I'll ask it in the forums.
lib/sudoku_fileparser.rb
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It file is not used outside this class, then it should probably be made private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @JoelQ, will change that.
lib/sudoku_fileparser.rb
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
split accepts a regular expression as it's splitting pattern. You could split on non-numeric characters like this:
parse_empties(line).split(/[^d]+/).map(&:to_i)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @JoelQ, didn't know split could do that.
lib/sudoku_unit.rb
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Nice syntactic sugar
…Unit. Good suggestion from joelq.
|
Thanks for all your feedback @JoelQ. Have a good christmas! 🍺 |
I really enjoyed this exercise! Super fun!
I've been reading up a lot on domain modelling and value objects recently, and so my design is heavily influenced by those ideas. I've also been meaning to test out aruba for a while – great little gem!
Design
FileParserconverts*.sudokofiles into a simple array format thatPuzzlecan use.Puzzleis made up ofRow,ColumnandBoxvalue objects. They all implement theUnitinterface (having looked up Sudoku on wikipedia, a Unit is the common term for all of these).Matrixin my implementation, and quite liked the interface forVectorwhen stumbling across it... so I can instantiate objects likeRow[1, 2, ..., 9]etc.Puzzleis aware of its own validity and completeness (wasn't too sure about whether this was a Puzzle's responsibility at first, but this is how it ended up. What do you think?)Validatortakes aPuzzleand can be sent:statusand:errorsthat can be output back onto the command line. (Unsure as to whether Validator is the right name for this object as it doesn't actually do the validating. Couldn't think of an alternative though...ideas?)Some things I was mindful of throughout the exercise:
Puzzlereceives its input.Some things I'm not so sure about
:==and:hashgumpf.Would love to hear your feedback, and I'll be checking out some of the other solutions on here too. These exercises are great – keep them coming!