Code Reviews with Exercism
I think code reviews can be great. I love learning from my mistakes as well as being challenged for my technical decisions. Code reviews provide this. Unfortunately it doesn’t happen nearly as much as I’d like. With high profile projects and deadlines always right around the corner, who has the time?
…and then I stumbled on http://exercism.io/. “Crowd-sourced code reviews on daily practice problems.”
I highly recommend you sign up and give it a shot. Whether you’re new to coding or enjoy the social aspect, this site has it. So here is the first challenge:
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
Bob answers 'Sure.' if you ask him a question.
He answers 'Woah, chill out!' if you yell at him (ALL CAPS).
He says 'Fine. Be that way!' if you address him without actually saying anything.
He answers 'Whatever.' to anything else.
Instructions
Run the test file, and fix each of the errors in turn. When you get the first test to pass, go to the first pending or skipped test, and make that pass as well. When all of the tests are passing, feel free to submit.
Remember that passing code is just the first step. The goal is to work towards a solution that is as readable and expressive as you can make it.
Have fun!
Code Revision 1
Nitpicks
Your class Bob is giving me undefined method 'upcase'
for nil:NilClass
when running the tests.
Also, your code may be more readable by using ruby methods such as String#empty?
and String#end_with?
to check for empty strings and strings that end with a question mark.
Lastly, you may also wish to separate these string methods into it’s own module or class.
-an anonymous nitpicker
I guess I should’ve read the feedback cycle before jumping in and coding, but thanks for the feedback you provided. Not only should I have caught nil but really anything that is not a String
.
On your second point though, I have to say I don’t totally agree.
So while String#empty?
May catch the empty case it wouldn’t catch the other, whereas the regexp does. I could go either way on
Both read fine, but the end_with? method would totally be clear to someone not as comfortable with regular expressions.
-mweppler
Forgot to mention… Chaining String#strip
with String#empty?
will do the trick. Also, using Object#to_s
can make sure your nil
messages get turned into strings. Regex does a perfect job, but I’ve noticed most nitpickers will nitpick in favor of ruby methods.
-an anonymous nitpicker
Code Revision 2
Code Revision 3
Nitpicks
I like!!! One thing.. the to_s.strip
can be added to line 9 to stream line. That way, line 3 becomes respond_with statement
and all your string manipulation is below.
-an anonymous nitpicker
What I am finding is that I need to return 'Whatever.'
if statement
is not a String
(catches nil
, Arrays
, Hashes
, etc…). Than if statement.strip.empty?
.
-mweppler
Read the Readme, the point if nothing was said, this means, empty
, nil
, white space
cause there are not words.
so statement.to_s.strip.empty?
would work in this case. these functions stack, so to_s
will turn any nil
to empty
the strip
will take out any white space
and turn the string to empty of nothing else
exists perhaps if you had methods like silence?
question?
and yelling?
it might make it more clear why the conditional statements exist.
-an anonymous nitpicker
I have read the readme and believe I understand the point. Lets think about your original statement “One thing.. the to_s.strip
can be added to line 9 to stream line”. Having it on line 3 guarantees what goes into the respond_with
method is a string
. Having it on line 9, sure if you pass nil
or an empty string it will return whats on line 10 as expected. Again, what about a case where you have an array
, hash
or some other object:
-mweppler
I do like the single responsibility principle you demonstrated
-mweppler
Code Revision 4
Nitpicks
I hate to have return ‘Whatever.’ twice, but I am finding it makes the most sense to me. Taking into account nil, and other non string object.
-mweppler
This doesn’t seem to pass the tests; I get two failures when I try it. I agree with you on not liking the duplication, but I believe one of the nitpicks on your previous version showed you a way to do this.
Also, in Ruby it’s generally better to check for capability than for class, so statement.respond_to?(:strip)
may be better than statement.class == String
, though I don’t think you need either here.
-an anonymous nitpicker
It would help to know what is not passing for you, since everything is passing on my end.
Also, the problem I see with respond_to? :strip
has to do with the ability to override or alias methods. Take the following for example:
or:
Ducktyping at its finest!
So unless you can guarantee your input won’t respond to strip you have edge cases to take care of.
-mweppler
This is what I get when I run your code:
And just to sanity check:
I agree that duck typing can lead to absurd things happening, but you can’t be too defensive without incurring a readability, performance, and sometimes functionality cost. What if there was another class that duck typed perfectly like a String
but was disallowed by your hey method? This can happen easily with String
vs IO
, for example.
However, I maintain that checking of the class or checking for methods is not needed in this case ;)
-an anonymous nitpicker
Odd that its failing for you… In any event I certain agree on not needing to resort to class checking, and have moved on to revision 5. Great feedback btw.
-mweppler
Code Revision 5
This looks great, but I would remove that begin
… rescue
, as Whatever is a valid response, it isn’t some kind of error situation.
-an anonymous nitpicker
…as you can see this can go on and on and on. Thats the fun part though (at least for me). This was only the first challenge but I feel like I am thinking more completely about solutions to the problem now that I have someone else checking my work ;)