I have noticed that the last few Ruby Conferences I have attended, Ancient City Ruby and Ruby Conf 2013, have not lived up to some of my expectations. This is not a fault of the conferences but of how I perceive improvements.
In the early days of Ruby, relatively speaking, when all the giant advancements were being made, like Rails, gems, migrations, rake, Capistrano and _why's latest ideas. I am sure we can all have our own lists of world altering ideas that fundamentally changed how we work every day. Some of this radicalization has waned.
I have been reflecting on how progress can be measured by tiny changes as well though the impact is slower and less measurable. For example, Jim Weirich works on Argus and, then Artoo changes how we approach Robotics in Ruby. Independently they are simple API's, but that simplicity becomes a fundamental driver of adoption and the growth of new ideas.
John Mair works on an improved Ruby shell and that simple improvement drives some re-birth of Small Talk ideas. What I can edit and interact with code at runtime? Small Talk got to where it is for many reasons both good and bad, but what will happen when we re-grow the good ideas into something new?
For me, I am going to pay more attention to the micro-drivers of our future. Keep it simple so that we can all be part of the growth.
Ruby is creating a thrilling world.
12/08/2013
RubyConf 2013 - What Changed?
8/17/2013
Ruby Warrior - Game Emulation
The output from my game emulator looks nice and allows me to great new alternative levels that exercise all the features of my player that I wish to.
GAME START
| ^ >|
| ^ >|
| ^ >|
| ^ >|
| ^ >|
| ^>|
| ^|
GAME OVER: ALIVE
GAME START
| ^ C >|
| ^C >|
| ^ >|
| ^ >|
| ^ >|
| ^ >|
| ^>|
| ^|
GAME OVER: ALIVE
GAME START
| ^ S >|
| ^S >|
| ^S >|
| ^S >|
| ^S >|
| ^S >|
| ^S >|
| ^S >|
| ^S >|
| ^ >|
| ^ >|
| ^ >|
| ^ >|
| ^>|
| ^|
GAME OVER: ALIVE
A simple rspec runner of these game layouts and a way to encode the game boards makes setup easy.
describe "Game" do
let(:player) { Player.new }
it "plays empty board" do
game = Game.new(" >")
game.play(player)
player.should be_alive
end
it "rescues a sad caged pair of eyes" do
game = Game.new(" C >")
game.play(player)
player.should be_alive
end
it "attacks some sludge" do
game = Game.new(" S >")
game.play(player)
player.should be_alive
end
end
The simple Game runner.
class Game
def initialize(pieces)
@pieces = pieces
end
def play(player)
warrior = Warrior.new
warrior.board = Board.new(@pieces)
puts "GAME START"
while (warrior.alive? && warrior.on_board?) do
puts warrior.board.with_player_at(warrior.position)
player.play_turn(warrior)
end
puts "GAME OVER: #{warrior.alive? ? 'ALIVE' : 'DEAD' }"
warrior.alive?
end
end
Ruby Warrior - Trying Again
It is clear that a solution to a problem like this can't just be imagined out of thin air. I am just not that smart. Just writing if statements was satisfying and productive to start with but once level 7 hit and I had to change direction there was no alternative but to throw everything away and start again.
This time, I decided to create a fake warrior implementation, an write some rspec tests to ensure that the actions I chose were appropriate. Then "release" (copy) that code to "production" (paste) to see if it worked there as well.
With this approach, I am making headway but can only solve level 2 because I haven't reimplemented the resting process yet.
Warrior Fake
class Warrior
attr_accessor :position
attr_accessor :board
def self.at_position_1
warrior = Warrior.new
warrior.position = 1
warrior
end
def self.next_to_sludge
warrior = Warrior.at_position_1
warrior.board = [:sludge]
warrior
end
def initialize
@position = 1 #zero based
@attacked = false
@board = []
end
def walk!
@position += 1
end
def attack!
@attacked = true
end
def has_attacked?
@attacked
end
def feel
@board
end
end
Player Implementation
require './warrior_fake'
class Context
end
class Action
def self.choose(warrior, context)
if !warrior.feel.empty?
Attack.new
else
Walk.new
end
end
end
class Walk
def run(warrior)
warrior.walk!
warrior
end
end
class Attack
def run(warrior)
warrior.attack!
warrior
end
end
class Player
def initialize
@context = Context.new
end
def play_turn(warrior)
action = Action.choose(warrior, @context)
action.run(warrior)
warrior
end
end
Specs
require './spec_helper'
require './warrior_fake'
require './warrior'
describe Player do
let(:player) { Player.new }
context "walking" do
it "moves forward" do
warrior = player.play_turn(Warrior.at_position_1)
warrior.position.should == 2
end
end
context "sludge" do
it "notices sludge" do
warrior = player.play_turn(Warrior.next_to_sludge)
warrior.should have_attacked
end
end
end
describe Action do
let(:context) { Context.new }
let(:warrior) { Warrior.at_position_1 }
context "construction" do
it "walks forward" do
action = Action.choose(warrior, context)
action.should be_a Walk
end
end
end
describe Walk do
it "forward" do
walk = Walk.new
warrior = walk.run(Warrior.at_position_1)
warrior.position.should == 2
end
end
describe Attack do
it "forward" do
attack = Attack.new
warrior = attack.run(Warrior.next_to_sludge)
warrior.should have_attacked
end
end
Thank-you Ruby Warrior
I just ventured into the dungeons of the Ruby Warrior and spent an hour of my life that I can not get back, but would like to if that is at all possible. What a great time to be writing ruby, to program a knight, in a live dungeon.
I made it to Level 7 before my code was so complex that refactoring is inevitable. I count at least infinity code smells in this. Flags, single method, no intentional behavior, no single responsibility. I am considering some UI testing tool to prove that I can pass each level with the same codebase.
Good times.
class Player
def play_turn(warrior)
if !warrior.feel(:backward).empty?
if warrior.feel(:backward).captive?
warrior.rescue! :backward
@saved_captive = true
else
warrior.attack! :backward
end
elsif !warrior.feel.empty?
if warrior.feel.captive?
warrior.rescue!
@saved_captive = true
else
warrior.attack!
end
elsif warrior.health < 20
if warrior.health < @health
if warrior.health < 12
warrior.walk! :backward
else
warrior.walk!
end
else
warrior.rest!
end
else
if @saved_captive
warrior.walk!
else
warrior.walk! :backward
end
end
@health = warrior.health
end
end
8/03/2013
Waterfall Disease - Symtoms, History and a Cure
It is easy to spot the symptoms in aggressive cases but can present in subtle ways as well. It effects individuals and teams and is communicable. The cure is long and slow but the young heal much faster. If you have been infected with this disease for more than 20 years, the chances of a full recovery is slim.
Symptoms
A programmer feels the strong urge to open a documentation tool before a code editor. This is not a guarantee of infection but a strong indicator.
An infected team will wait for a task to be given to them and then talk about how it is the wrong task or how long it will take to implement. Similarly infected product owners will first ask how long before asking what should be accomplished.
A programmer will, when asked what it would take to implement a feature, answers in terms of the complexity and duration. For example, "OH that would be difficult, we would even have to change the code", or "We would have to talk to that other team, so that will take much longer".
An infected team or programmer assumes that the deadline means they will have to hack in a bad fix, even when there is no stated deadline. These individuals just assume that they will be pushed to make bad decisions so make them as the default, as thought there is no other approach.
A team member states "that is his responsibility", or makes a suggestion or proposal for a change like "I think we should do X". Each of these forms of communication relinquishes responsibility to others, ensuring that the team member does not have to take ownership of the idea they are sharing.
A team member will hand-off a task with the statement "you need to do X so that we can accomplish goal Y". This team member will, and watch for this for it is quick, turn on their heals quicker than normal, and walk away with a slight smile believing they have helped but actually are just passed the blame.
An infected team member will act out, taking actions in direct opposition to the teams goals, and other infected members will watch as though they have no control. They are thinking that the boss should fire that person, not realizing that they should also be considered.
History
Waterfall disease has been with us for decades. Until the late 1990's it was thought of as normal, even part of the best practice of what a programmer was. Only as the year 2000 approached and the new Agile medicine was introduced to the market did everyone start thinking that there might be another way.
Unfortunately, this Agile medicine tastes very bad and patients remain in denial of the problems, just because of that possible bad taste. It is not uncommon for teams, thrashing uncontrollably and screaming about the unacceptability of their plight, to also state that "the medicine will never work" and refuse to sign-up for the treatment program.
Cure
The treatment for waterfall disease is not easy and takes time. Unfortunately, this conflicts directly with the infected parties who have no patience for change.
The cure comes in 3 main phases: a strict diet of learning, combined with the constant guidance of mentors to re-map the brain pathways and finally a change inoculation.
The learning pills must be dosed carefully across time to avoid overload. An ideal learning pill regimen might look like this though results may vary depending on how acute the infection is.
- Complete removal from the environment that promotes the infection. This might mean leaving the programming environment, the building where re-contamination is possible or even, in the most aggressive cases, leaving the company that actively promotes the disease, is the only way to avoid a relapse.
- Daily doses of TDD to begin with interspersed with insights into why the current feelings they are experiencing are actually not normal. Knowing that they have a problem is an excellent step toward recovery but do not expect this to occur in these first rounds. Continue this repetitively for 2 weeks switching from a training environment to a practice environment until you start seeing the natural antibodies of the human body kick into gear. These changes show themselves in the form of surprised questions like "so this actually means I don't have to fix bugs anymore"?. Be gentle with the initial naive questions for the physical changes that are underway are only loosely bonded.
- At some point a sense of wonder, and excitement about the future starts to seep in. Recognizing these moments is key to cementing the changes and reducing the possibility of relapse. Show your excitement about the future and talk of your new life, clean of disease.
- Once two "sense of wonder" moments have passed it is time to move to the next phase of treatment. Collect one or more of these patients into a team and task them with a green field solution. The use of a green field solution simplifies the continuing diagnostic work that is going to be necessary as the work progresses. This also starts the mentoring phase of the cure.
- Mid-night implementation of a new feature. Attempted under the guise of improving the teams velocity (and they will use that word even if they do not understand it), but actually, this action is driving a sense of self-congratulatory excitement of achieving goals without the mentor's gaze and without tests. Protect against this with early investment in fully automated functional tests. The next days failing build will identify the culprit and allow the mentoring to focus appropriate action.
- Active creation of cliques, through a sub-team secret design sessions that can then be presented as great successes to the team, when in-fact, they serve more to isolate and inject mistrust amongst the team members.
- Little code changes without tests will leak into the codebase, often with a source control comment unrelated to the change or misdirecting the mentor to a larger change. When challenged the response will likely be a sheepish grin, as though that still works now that they are fully grown up adults, and the statement like "that was just a one character change", or "its only in a tool, not the real app". These are actions that must be stopped, in group therapy sessions, to ensure that everyone agrees that they want to be cured.
- Throw away all desktop computers and replace them with laptops to promote movement. In the same vein, ensure that wireless network access is available and the old wire is disconnected.
- Interrupt the team with cake but do not take it to their desks. Instead, place it 20 feet from them so that they are encouraged to move. Repeating this makes movement more normal and bridges the gap to a time when movement to communicate with team members is the new habit.
- Mandate pair programming and make sure that it is with new people all the time. Having to work with team mates ensure that they know each other's names and start gaining insight into other cube silo's.
- More radical, but utterly required to ensure success, is the removal of cubical sitting structures. Some powerful conversations with CIO's will be necessary to drive this kind of medication.
- Disabling email for periods of time forces movement for simple conversations, changing the quality of communication so much that teams will start experiencing a high velocity team feature known as "common thought". At first this is startling, and must be called out by mentors as a healing step, but will soon become the natural order in which simple 30-second exchanges can accomplish what was once days worth of drifting, misinterpreted email exchanges.