99 Bottles of OOP – Shameless Green

I’ve been reading through Katrina Owen’s and Sandi Metz’s latest book 99 Bottles of OOP. I have a history with Object Oriented languages and wasn’t sure what to expect but I have been pleasantly surprised.

99 Bottles starts with the Beer Song exercise over at Exercism.io. You are tasked to write a class that puts out the verses to ’99 bottles of beer’. There are 4 different solutions presented, all based on different needs.

The last example, Shameless Green, is the preferred. It’s redundant and has no scrap of DRY. However, it passes all the tests and is the easiest to read.

My solution extrapolated every duplication. The flog score for my code is 42.3 while the flog score of Shameless green is 29.3. That’s a significant difference.

This was very interesting to me and I think the authors pin me down in their summary:

“As programmers grow, they get better at solving challenging problems, and become comfortable with complexity. This higher level of comfort sometimes leads to the belief that complexity is inevitable, as if it’s the natural, inescapable state of all finished code. However, there’s something beyond complexity—a higher level of simplicity. Infinitely experienced programmers do not write infinitely complex code; they write code that’s blindingly simple.”

Excerpt From: Sandi Metz, Katrina Owen. “99 Bottles of OOP.”

Test Doubles

The other day I broke our tests by including a Module that required configuration. I didn’t realize this until our Continuous Integration setup reported failures. If I wanted to get my pull request through I would need those tests to pass. One dev recommended a test adapter. I began designing and thinking of a solution to get this module working while testing.

However, another dev had a much simpler solution and resolved it with a single line in the spec:

allow(Mail::NewUser).to receive(:send)

RSpec refers to this as a Test Double, after Martin Fowlers article. The idea is that our tests are specific to a single value or behavior. However, these can unexpectedly change when they depend on another object’s value or behavior. If we can replace that dependency with an object providing consistent behavior we can keep our tests simple and clean.

Suppose I want to test a Hello module. It accepts an instance of Person and says hello.

module Hello
  def Hello.person(person)
    "Hello #{person.name}"
  end
end

An issue with testing this module is that the Person class is complex. While person.name is expected to be a short string, it’s a complicated algorithm to generate and create.

This shouldn’t be an interruption to creating the Hello test. It’s also not the time to think about the Person class. How can we test the Hello module’s behavior without having an instance of Person readily available?

Below I have created two tests. The first uses an Open Struct to provide the needed behavior to test Hello.person. The second uses RSpec’s doubles to create an instance of Person. It also has a ‘name’ method to call and return the value ‘Dave’.

RSpec.describe "Hello" do
  it "accepts a dummy object to greet" do
    require 'ostruct'
    dave = OpenStruct.new(name: 'Dave')
    expect(Hello.person(dave)).to eq("Hello Dave")
  end

  it "uses a test double to greet" do
    dave = double("Person", name: "Dave")
    expect(Hello.person(dave)).to eq("Hello Dave")
  end
end

These tests are only concerned with the Hello Module. They do it with minimal knowledge of what the Person class is. Whatever happens to Person, this test double will always remain the same, leaving our tests safe and happy.

Test doubles are beneficial.

  • They enable you to be lazy. In our example we didn’t need to know the Person object to test Hello.
  • They prevent things from creeping into our tests that we are not testing.

I hope this overview of Test Doubles helped you understand testing. I recommend the RSpec Mock documents for a full overview of RSpec and test doubles.

http://www.relishapp.com/rspec/rspec-mocks/v/3-5/docs

Uncle Bob has also written a helpful article on the strengths and weaknesses of mocks, https://8thlight.com/blog/uncle-bob/2014/05/10/WhenToMock.html.

Quick PostgreSQL Backup

I recently learned the hard way that brew update can break a PostgreSQL install. Googling around there seem to be a variety of problems and solutions to this scenario.

I was able to get back up and running by relinking my PostgreSQL installation. That seems too easy. I now live with the nagging doubt that something worse is waiting for me in my PostgreSQL install.

To quickly setup a backup process I use the command pg_dumpall in tandem with gzip. pg_dumpall creates a SQL file to recreate my databases and gzip compresses it.

In testing, a pg_dumpall produces a 937M file. Using it with gzip downsizes it to 137M.

Here is the command below. I’ve configured this in my cron jobs to happen every evening Monday through Friday.


pg_dumpall --clean | gzip -c > dev_db.psql.gz

Restoring from backup is just as easy.

gunzip dev_db.psql.gz
psql -f dev_db.psql postgres