24 Sep 2012
Ah, constructors. The little, forgotten, and often abused thing. No one really thinks about it for long, no one really knows what it does. Everyone tends to ignore it until they think they need it and throws things into it with no care whatsoever. Yes, the constructor might be the best equivalent to a homeless child.
And yet, recently, I started thinking more and more about
homeless children constructors. They are a defining character of all object-oriented programming languages. And they do fulfill an important role! So let's learn a bit more about the homeless constructor.
Do's in a Constructor
Ever had a class that felt awkward to use? Where you, in practically ever method, first checked if some precondition was fulfilled? That might mean you have forgotten to put something in a constructor.
The simple rule is:
Everything the class needs in order to work goes into the constructor. For example, recently I wrote a small proxy to
Nokogiri. The class looked something like this:
class XmlHelper
def open(file)
@file = Nokogiri::XML(file)
end
def find_uas
raise 'Open the file first' unless @file
# read file etc.
end
end
With one method, that might work. But how would I add a second method here? I would have to do the same check if the file is actually opened again. Which means
the class isn't ready for operation after the constructor is called! So I fixed this the easy (but hey, stylish!) way:
class XmlHelper
def initialize(file)
@file = Nokogiri::XML(file)
end
def find_uas
raise 'Open the file first' unless @file
# read file etc.
end
end
Yes, one small change. From now on, when someone wants to make an instance of XmlHelper, he
has to provide a file to read. Which means the class is ready to be used.
Put things into the constructor if the class can't feasibly be used without it.
Another great use of constructors? Dependencies! Of course, you could add a dependency like that:
class Limb
@child = Child.new
end
We have two problems with this:
- The Limb class knows too much about its surroundings. Maybe it just needs to tell the child that it is tired. But what if we suddenly want to use the Limb class with an Adult? A dog? We can't do that with this implementation!
- Another problem is testing. We can't, in a unit test, easily replace Child with a mock or a stub. Maybe instantiation of a child is difficult (it takes 9 months for gods sake!) Or we simply want to test the interaction between Limb and Child, which is difficult if we don't know to which Child this Limb is talking to. (Remember: A constructor shouldn't do real work!)
The better way to do it?
class Limb
def initialize(body)
@body = body
end
end
Ah, now it's obvious, right? We can simply add a new body that this Limb belongs to. And the Limb doesn't care anymore if it is a child or not. For the lazy who don't want to type
Limb.new(child) all the time, we can also change the initialize call to
def initialize(body = Child.new) ... end so the Child is automatically added if we don't specify something else.
But Don't Put These Things Into the Constructor!
So now that we have a usable object after construction, what doesn't belong in there? Should we just throw everything into there?
Now that we know what to throw into a constructor, it is easy what not to throw into a constructor. In short: Everything else. If not every method in the class needs this property, if the class doesn't need this information to work correctly, then don't add it to the constructor! If some methods need a property, and the others don't, you probably should split the class up into two.
They deal with different things.
One special thing though: If the initialization logic is very complex, it might be better to put it into a builder. A builder is a separate object that can be used to build up an object. It can even build objects of different classes (that have the same method, of course) given different input.
Ah, So That's Constructors!
Yes, so it is. So please stop abusing the little homeless kid on the block and treat it with the kindness it deserves. It shouldn't be dropped all responsibilities, but don't forget that it is there and you can use it.
To summarize:
Pass a constructor all the information the class needs to work properly, but nothing more.
Have I forgotten some use case for constructors? Do you know some other constructor abuse cases? Then drop a line either here in the comments or on
Twitter!
If you liked this post, you should consider hiring me freelance, part-time or full-time!
17 Sep 2012
Just recently
Jim Weirich released
rspec-given 2.0, an extension to the RSpec DSL. It tries to add
given,
when,
then semantics to RSpec. Why? Because
given,
when,
then state
intent. So everything in a
given will be something that you expect to be present.
when is the part that should actually be tested and
then states what should happen.
This makes it easier to see what is just a test helper, which code is actually under test and what should happen to the different moving parts. Go read the
readme in the rspec-given repository, Jim does a way more thorough job at explaining the semantics. Or if you know Cucumber, you can just continue! For the rest, I will be waiting, right here.
Back already? Good! Let's continue!
A Primer on RSpec Given
So, if we want to write a Math library that uses a very strange notation, a spec could look like this:
describe "Math" do
describe "#+" do
it "adds two values" do
let(:value_one) { 2 }
let(:value_two) { 3 }
Math.+ value_one, value_two
Math.result.should == 5
end
end
end
I know, I know, it's a very contrived example, sorry... :(
But what are we testing now?
Math.+ or
Math.result?
With rspec-given, we could specify intent a lot clearer:
describe "Math" do
describe "#+" do
context "adds two values" do
Given(:value_one) {2}
Given(:value_two) {3}
When { Math.+ value_one, value_two }
Then { Math.result.should == 5 }
end
end
end
So we have two preconditions (setting
value_one and
value_two), which are just there to help the test. Then we have the code we actually want to test (
Math.+). And we have a post condition, that needs to be true at the end. But in the second example it is clear that we don't test
Math.result, but
Math.+! Also notice that
then replaces the need for an
it block.
I guess we all can agree that the second example is way more specific which code is there for what purpose. Which I like.
But that got me to ask one question: How do you extend the DSL? Let's see:
Extending DSLs
First things first (because it wouldn't make sense to mention the first thing at the end I guess? That saying has never made sense to me, sorry...), I'm looking at rspec-given-2.0.0.beta3. This way, Jim can't ninja change things in there and then tell me I'm totally wrong.
Second things second (that doesn't exist, does it?): Let's have a look at the first file:
rspec/given.rb. If we ignore RSpec 1 (someones still using that?), we include different files. One of the interesting files is configure.rb. Here the important lines (actually, all lines in this file except the includes):
RSpec.configure do |c|
c.extend(RSpec::Given::ClassExtensions)
c.include(RSpec::Given::InstanceExtensions)
c.include(RSpec::Given::HaveFailed)
end
(
On Github)
He uses RSpec.configure to extend and include a few extensions. If we take a look at RSpecs rubydocs, we can find
RSpec.configure. Even more important, the Configuration object has two methods:
extend and
include! Now that's handy, because that's exactly what we used!
These two are really similar.
#extend is used to add methods to example groups (but not the examples itself). It is added to the
describe block, but not the
it block.
Now guess what
#include does. Right! It adds methods to the example itself, but not to the example group!
Now we know how we can add custom stuff to RSpec examples and example groups! Which is exactly what rspec-given does!
The class and instance extensions can be seen in
extensions.rb.
That's How You Extend a DSL
RSpec nicely enough provided everything we need to extend it's syntax with our own methods. Of course this isn't just handy for rspec-given. Everyone can extend RSpec with its own syntax, which might come in handy once in a while.
I suggest you have a look at the
RSpec Configuration object, because it can actually do a lot. Did you know that it can show you the 10 slowest examples, automatically? Or that RSpec has
before, after, and around hooks?
So not only have we learned what rspec-given is, how it works, but also how we can extend RSpec ourselves! Thanks Jim!
If you liked this post, you should consider hiring me freelance, part-time or full-time!
10 Sep 2012
Fun Fact: You most likely fall into the same trap that I do: The expert's dilemma!
The Expert's Dilemma?
Yes, the expert's dilemma. What is it, you might ask. In fact, if you don't ask yourself this question right now, why are you even reading? Maybe this piece then isn't for you. If you are, however, wondering what that is and why you most likely also fall into this trap, read on.
The expert's dilemma is quite simple: We try to emulate experts as well as we can. We try to listen to their opinions, follow them, and carry out everything they say. The problem with that? If you are not an expert,
most of the things they say don't matter to you!
Yes, seriously!
Let me illustrate through two examples: Fitness and Starcraft II. I know, I know, both of those have nothing to do with programming (except that progamer looks almost like programmer), but bear with me. Just a moment now.
Let's talk about Starcraft II
Starcraft II is a really simple game. You have so-called harvesters, that gather resources. With these resources you can build more gatherers, units to attack or defend, or new structures and research to make everything stronger. Simple as that.
Now of course the pros are talking about balance, and that this unit might be a bit better if it had one attack power more than it has now. Or that if you delay action X, you can do action Y Z seconds faster. And other such fun things. If you follow all this advice, you fall into the trap of the expert's dilemma.
When I started playing Starcraft II, it worked something like this:
Andreas: "Wohoo, I play Starcraft II. Let's just try to play so I have fun!"
The Pro: "But Andreas, what are you doing? You should have a plan, you should scout your opponent!"
One week later
Andreas: "Whohoo, I play Starcraft II. I even scout!"
The Pro: "But Andreas, what are you doing? You should control each unit into his last detail!"
One week later
Andreas: "Wohoo, I have a lot of free time!"
Why did that happen? Because I tried to follow all the experts advice, I forgot that I first need to learn the basics: Gathering resources! So I started to lose a lot and I quit.
So all the questions about balance and all that don't play a role for people like me, because other things play a much bigger role. For the pros who play all in the same percentile, they do. But for me?
Let's talk about fitness
Ah, fitness. Where everyone has an opinion. And everyone has a different opinion. It sucks! It makes it hard to start. So let's take the journey for a normal beginner (like me!):
Andreas: "Wohoo, I started with a fitness routine! So I run a few times per week and do some bodyweight exercises."
The Pro: "But Andreas, what are you doing? Running hurts your muscle gain, so stop that!"
One week later
Andreas: "Wohoo, I started to do a lot of bodyweight exercises!"
The Pro: "But Andreas, what are you doing? If you would vary them more, you could get better results! Also, start doing them on 5 days instead of 3."
One week later
Andreas: "Wohoo, I'm playing Starcraft II!"
Queue a rage comic here...
Result: Instead of following what I was doing and enjoying, I stopped doing anything. Instead of getting 80% of the results, I now get 0%!
This Is A Blog About Programming, Right?
Yes, absolutely. Now let me tie it back to programming.
TDD, BDD, refactoring,
SOLID, performance, method to line ration, line per class ratio, test coverage, newest trends, etc. etc. etc. Sounds familiar? Do you get it now? No?
Damn it!
That was the point of the whole post.
Let me try again: There are a lot of buzzwords and other things to follow, which can choke a beginner. A beginner should be doing. (
Careful: Controversial statement following!) If it isn't perfect, who cares?
It is more important to do than to do it perfectly!
Experts Are Nice, But...
I know the experts just mean well. But a beginner or intermediate
can't possibly follow all advice! It will confuse her or him more than actually following through with it!
So don't blindly follow experts advice, just keep being awesome and improving along the way!
Don't get bogged down, don't try to do it all perfectly from the beginning. Add stuff slowly and concentrate on the basics. Because like in Starcraft II and in fitness, it is better to do the basics right than butchering all the experts advice.
Did you fall into this trap yet? Share your (horror?) stories!
If you liked this post, you should consider hiring me freelance, part-time or full-time!
03 Sep 2012
Developing a Rails application is awesome. Why? Because the testing stack is really, really good! But, this is also a problem. There is so much to choose from, that it sometimes is really hard to figure out what is useful and what isn't.
I don't know about you, but my Gemfile tends to have a lot of stuff in the group
:development, :test.
group :development, :test do
gem 'rspec-rails'
gem 'cucumber-rails', :require => false
gem 'database_cleaner'
gem 'capybara'
gem 'launchy'
gem 'rr'
gem 'awesome_print'
gem 'jasminerice'
gem 'guard-jasmine'
gem 'poltergeist'
end
Holy crap that's big! Of course, it also has some helpers only for development:
group :development do
gem 'guard'
gem 'libnotify'
gem 'guard-spork'
gem 'guard-cucumber'
gem 'guard-rspec'
gem 'guard-livereload'
gem 'spork'
gem 'pry-rails'
gem 'pry-stack_explorer'
gem 'pry-debugger'
end
Not too shaby, huh? So let me get into the details for each of those.
Guard
Guard is an amazing tool to automate nearly everything. Don't believe me? Take a look at all the possible
Guard extensions on Github! So what does Guard do?
It basically is a system that runs in the background and can watch files. Extensions tell it (through a
Guardfile
) that it should do something if a specific file pattern changes. For example, the
Cucumber guard checks for this:
guard 'cucumber', :cli => "--drb" do
watch(%r{^features/.+\.feature$})
watch(%r{^features/support/.+$}) { 'features' }
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
end
It looks at all features in the features directory, and Guard will call the Cucumber guard if one of these files changes. In term, guard-cucumber will call Cucumber and show it to you on the console. Neat, isn't it?
Of course, this isn't just for Cucumber! I also use the
RSpec guard (for RSpec tests, duh!),
Spork and
livereload.
Spork is a DRb (Distributed Ruby) server that preloads the Rails environment so the tests run faster. Adding this guard makes Guard start the DRb server for Cucumber and RSpec automatically when starting Guard itself.
Another very neat guard is guard-livereload. Thanks to an extension in Chrome, this guard will automatically reload the page I have open when I change the ERb or the CSS files. Makes fiddling with CSS a lot easier!
You Have To PRY It From My Cold Dead Hands
PRY is one of those tools that you just have to know (and love). It is an alternative to IRB, and way better! Just add a
binding.pry to your code and Pry will open in that context when the code runs over it. It allows you to change into classes and objects to inspect them more closely. And edit the methods if you want to!
Some additions I added to Pry (and there are a few
Pry plugins) are
pry-debugger, so I can step through code and see what it really does. To complement Pry Debugger, I also use
pry-stack_explorer. This plugin allows us to move up the stack and see the state of the code there.
Of course, in a perfect world, we never have to use one of these tools, but yeah... Real world and these things...
Testing tools
You might now say: "Hey! You said you will talk about
testing tools, not support tools!" And you are right! (Though these support tools are amazing for testing!)
Yes, testing tools. For my testing needs I use the standard combo
RSpec,
Cucumber,
database_cleaner,
Capybara and
rr stack. I don't think I have to explain these (Do I? If I do, you should tell me so in the comments!)
Additionally I use
launchy to launch a browser window with the current state of the page to debug Cucumber steps.
I also make copious use of
awesome_print, because it is, well, awesome! awesome_print can be used instead of
puts or
pp to output objects and have an easier time inspecting them. (Pry also can use awesome_print for it's built in printing habits!)
Last But Not Least: JavaScript Testing
Something I struggled with for a bit, but found a good solution for, is JavaScript testing. There are two aspects here: One is Cucumbers Javascript support. For some acceptance tests, I needed Javascript to run. Per default, Cucumber uses Selenium (with a real browser), which is slow and not awesome at all! And then there are the Javascript unit tests, that also need to run.
For the unit tests I settled on
Jasmine. Why? Because it seems it even tries to be as close to RSpec as possible, so I don't have to learn yet another testing system. To run them, I of course, use a guard:
guard-jasmine (Who's surprised?)
guard-jasmine uses
PhantomJS to run the Javascript tests in a headless mode (without a user interface), which makes them fast (not incredibly fast, but at least fast).
Of course we also want to integrate the Jasmine unit tests with the asset pipeline so we can use CoffeeScript. Luckily, Brad Phelan solved that problem and released
JasmineRice.
Now, this doesn't yet solve the Cucumber problem. For that, we can use
Poltergeist. Poltergeist is a PhantomJS driver for Capybara. Do you see how this neatly matches up with guard-jasmine? Nice, isn't it? I just configured Capybara to use Poltergeist instead of Selenium, and now the tests run at an acceptable rate.
So, What's Your stack?
Yes, that is my "standard" Rails testing stack. I think this covers about everything I need. One thing that's not included (because I currently don't need it) is something like
VCR. VCR records HTTP interactions, so that during testing the HTTP calls don't have to be made, but can be replayed by VCR. Which makes things even quicker.
Have I missed something? Added something superfluous? What do you use for your testing stack?
If you liked this post, you should follow me on Twitter and sign up for the RSS feed!
27 Aug 2012
Starting with Ruby isn't easy. Especially if you are like me. I have, like many before me, a Java background. So I knew statically typed languages, I knew what it meant, I knew what its strength were.
And, like the monkey that I was, I thought statically typed languages were the best! Why? IDEs have a really easy time to refactor a lot of code. Everything was clear. Well, you know, the standard arguments you probably also here when we talk about statically typed languages.
But this post has nothing to do with statically typed languages, with me having seen the light at the of the tunnel and all that. And since you are reading this, I guess you did the same!
But, fun fact, here, for free, no sign-up needed: Ruby can do a lot more. A lot! And it has it warts, and it has its way of doing things. This isn't easy to understand when you are knew, or even when you are experienced.
So here are 3 tips on what you could learn from reading
Eloquent Ruby by
Russ Olsen:
Strings In Ruby Are Awesome! Literally!
Ever had to write a string in Java? I feel sorry for you, because I have written way too many back in the days. Remember
"This is a \"String\"" or even better, a Regex? (Hint:
"\\..*", and yes, that's basically a smiley. That's also my theory that smilies are a result of Java programmers using Regex).
The first string problem is easy to solve in Ruby: Just use a single quote! But even better, if you mix single and double quotes in a sentence ("And here shall "REST" Java. It's done.") we can solve this with a string literal:
%q{And here shall "REST" Java. It's done.}. See? No problem. In fact, we could even replace { with '$', since we never use a '$' in our sentence! Or a lot of other special characters for that matter.
The Regex (
or Regexp?) we could write as
/\..*/. No double escaping needed! And yes, it still resembles a smiley, I realize that. It's still a Regex after all!
There is a lot more that can be done with string literals, so you should check that out in the book!
Ruby Has Hooks For A Lot Of Things
Ever written a module? Imagine that you are that module. This is carry stuff! Just think about it: You have to blindly stumble around, never knowing which class carries you around!
Luckily, Ruby offers us hooks that we can use to alleviate these problems. Each module has a
self.included method that you can use. It is called every time a class, well, includes this module. Even better, it even tells you which class it was!
This way you can build up a list of all classes that have this module included. Doesn't sound very handy? But maybe, when the module is included, you also want to extend that class. Maybe you have a method that should not be on the class, but on the object!
With
self.included and other hooks, everything's possible!
How To Build Your Own DSL
DSLs. How much we all love these little things, and how much we use them each and every day. Thank you, dynamic typing!
Probably you have at least seen some RSpec code. Yes, all that
let,
describe, and other syntactic sugar is just a DSL, implemented in Ruby. Do you want to know how to do this? Then go read the book! It has a few caveats that I can't all list here, because this is just a blog, not a book!
Even better, he also mentions how to build an external DSL. An external DSL is not written in Ruby, and has to be parsed "by hand" with Ruby (without the Ruby interpreter helping). Which does have its pros and cons, as you might imagine.
Conclusion
All in all, a very good book that opened my eyes (and still does, on my second reading of it!). One of the really nice features about the book is its structure. Russ gives us first an introduction why we want to do this, then tells us how. So far so good.
But then he continues: He also tells us how you can get in trouble with it. To top it off, he shows some examples of the described concept in the wild.
If you are a Rubyist and you haven't yet read
Eloquent Ruby, I highly suggest you do. Because Ruby can do a lot more than you might image!
If you liked this post, you should follow me on Twitter and sign up for the RSS feed!