Software Etc.

Guy who love software and cares about its community.

I am currently a software developer with Hunter Industries. The postings on this site are my own and don’t necessarily represent Hunter Industries’ positions, strategies, or opinions.

Making a Safe Place to Work


Thanks

This post is a special thank you to @JoshuaKerievsky. First I do not work with Joshua, or am I associated with him, however he has inspired a large amount of good things within my team.

Safety is a Skill

Bringing safety to the place I work is one of my highest priorities. Now to be fair, my place to work is the most safe place to work I can imagine. So why do I focus on bringing safety to my work?

Safety is a skill. It is why all manufacturing companies have mandatory safety training. But these trainings only cover one type of safety.

Psychological Safety

Google discovered that psychological safety is the key to a well functioning team. We have seen similar successes in our team well before this article was written.

Core Rules

My team's core rules have been in place for almost 4 years (as of September 2016). They focus on building psychological safety. They are:

1.      Treat everyone with Kindness

2.      Treat everyone with Consideration

3.      Treat everyone with Respect

The first thing to notice is the word everyone. This is not just those you work with. It is not just the people within your department, company or developer community. It says everyone, and it means everyone. It also means that everyone you work with will do the same.

The Cards

I won a raffle held by Industrial Logic, Joshua's company. The prize came with a small number of these cards:

 


The back states you have the authority to stop work if any of these things are at risk:

1.      Time

2.      Information

3.      Reputation

4.      Money

5.      Health

6.      Relationships

I instantly fell in love. I gave each member of my department one of the cards. I made discussing the cards part of the onboarding process. At the end of which I gave the new hire the card.

On Boarding with Safety

I inform every employee that they have great authority when they come to work here. They can stop work if they feel the any action another is taking threatens any of those things. I then express how our practices, Test Driven Development, Continuous Integration, Mob Programming, and others help to protect these things.

The new hire now has the authority to stop our work if anyone violates these practices unless the reason is to experiment on finding a better, safer way. Even then it is there priority to call attention to these violations, question them, and evaluate the experiments experiments to determine their safety.

Then I tell them the hard part of this authority. They do not only have the authority, but the responsibility. It is part of the job requirement that they do this. Ignoring these hazards is willfully not doing your job.

One of the best moments of my career was when I told this to our interns. They could not believe any company would give them such responsibility and power.

Part of our culture

A number of us have attached the card to our badges, as a reminder of how important this really is. We retrospect often and try to do things that promote this safety. I think we are better then any company I have ever heard of it this regard. However, I do not believe we are perfect or finished. The company recognizes that this safety has obviously contributed to our success and we are dedicated to finding better ways to achieve it or grow it.

The problem with the #NoEstimates Debate

The problem with the #NoEstimates debate is that both sides are not arguing the same thing and therefore the debate focuses on invalid points. The #NoEstimates hash tag has almost nothing to do with estimates, despite the focus the debates have. What is really being discussed is fundamental ways of doing business.  The pro #NoEstimates group is talking about a fundamental shift in how business is being done. We are talking about regulating and controlling price of software in a very different way.

Without changing, in entirety, the way in which business is done then a lot of the concerns the anti-#NoEstimates group bring up are valid. However, we are talking about a fundamentally different way of doing business.

The basic tenant of #NoEstimates is to change the way that decisions are made. We start with the assumption that the market is moving faster than we can. If this is true, then anything that delays getting a product to market has a huge cost associated with it. This cost is measured in employee hours, loss of customer faith, and competition gaining market shares before us.

The second tenant is that we are going to make mistakes. We are human, and therefore it is impossible to be correct all the time. If we are going to make mistakes, then let’s minimize those mistakes. We want to release small pieces of functionality often so that we can get feedback quickly. We can use this feedback to find mistakes before they are big and costly.

The third tenant is that the market will move with the introduction of product. Once the customer gets any functionality that is useful to them, that functionality will change what they want from future functionality. We have to be able to sense and move with that change.

This brings us full circle. The market is going to change faster than we can.

#NoEstimates is a way of doing business that attempts to accept these three tenants, while ethically helping companies navigate the new landscape of business. We do this by making business decisions in real-time and trying experiments in the marketplace to determine real value. We make decisions based on evidence instead of estimates.   

A Better Interview

It is important to get interviewing right: it is the first impression a company has of a candidate and the first impression a candidate has of the company. My goal with this article is to start an open discussion about interviewing and how we can improve it. As a community we need feedback, debate and understanding to create something better. The place I work currently has the best interview process I have ever seen in my 17 plus years in this field. By examining what they do and why they do it, the discussion can open with a solid foundation. We can build upon this to achieve something greater. 

Where do we Start

The Hunter Software Development Group is built off of three core rules, and those rules permeate everything we do, including the interview process:

  1. Show everyone kindness.
  2. Show everyone consideration.
  3. Show everyone respect.

These are our foundations upon which we build everything. We believe every facet of an interview process should be executed with these in mind.

When you consider kindness, consideration and respect as the foundation for an interview, your goals change shape. Yes, you need to know if the candidate is right for the job, but how you determine that changes subtly as your focus changes.

There are three conditions for an interview being considered successful:

  1. The candidate leaves feeling fairly assessed.
  2. We know if the candidate will be a good fit for the team and company.
  3. The candidate knows if the team and company is a good fit for them.

Achieving those Objectives

Each objective is achieved through very intentional means. We examine our process after every interview. We look for any place where the process can be polished, or someone can be better trained. We focus on each objective to better our process and make the interview successful for both the candidate and the company.

The candidate leaves feeling fairly assessed.

It is difficult to judge the capabilities of an individual within a small time frame. It is harder to do that in a way that feels fair and just. We try our best to accomplish this goal by tackling the idea from a number of sides. In order to talk about how a candidate is assessed, it is important to know what they are assessed for.

The traits that we are trying to assess are:

  1. How much emotional intelligence has the candidate acquired so far?
  2. What unique technical background and skills does the candidate bring?
  3. What aspect of programming does the candidate shine in?
  4. How much does the candidate know about Extreme Programming?

The first thing that happens is the candidate is given an explanation of the interview process. They are told what will happen, what they are evaluated on and why. It is important to eliminate surprise wherever possible. We believe this level of transparency is essential to the accomplishing our three goals.

Once the interview has been explained, there are a number of programming problems that the candidate is asked to work through. Each problem is straightforward with no obscure programming knowledge required. There are no riddles or surprises. Each exercise allows candidates to demonstrate a host of different skills as they work toward different solutions.

As they work through the problems, they have the opportunity to be given help and advice by three to four programmers that have been designated as their team. The team will not give solutions, instead they will help with programming language knowledge and design advice. The team will also rotate into the interview, giving the candidate a chance to navigate, teach, and guide various people with different skill sets.

There is a proctor, a person who takes lead on the interview. The proctor works as a guide for the candidate, helping keep them on target, and moving smoothly through each problem. It is the proctor’s responsibility to ensure the candidate understands what is happening throughout the interview.

Lastly, the candidate is not expected to solve the problems. In most cases it is not possible to finish in the allotted time. The purpose of the exercises is not the solution, but the path taken. We are not focused on what the candidate does not know, but rather the unique experiences and strengths the candidate brings forward.

We know if the candidate will be a good fit for the team.

There is a lot to consider and understand when talking about team fit. The Hunter Software Development Group works very differently than any place I have ever worked. We use a practice called “Mob Programming” to do all of our daily tasks. This means that all production code is written in a highly collaborative environment.

The factors that are key for our work environment are:

  1. Can the candidate communicate collaboratively?
  2. How does the candidate research new information?
  3. Do they demonstrate kindness, consideration, and respect?

Being part of a collaborative team is essential for anyone working in a Mob Programming format. Candidates will be asked explain how to solve problems and sometimes navigate a member of their team through the process of solving a problem. This means that one of their team sits at the keyboard and the candidate is asked to tell the teammate what to do. The disconnect from the keyboard forces some form of communication between the team and the candidate. Each of the team members is at a different skill level for different sets of skills. Inevitably, the candidates will either guide someone that is currently more skilled than they are or a teammate who is less skilled than they are. The way the candidate handles these two situations provides invaluable insight into that person’s communication style. It is important that the candidate shows kindness, consideration and respect during the whole process.

The processes of our everyday work environment puts highly collaborative teams into situations where they are acquiring new knowledge. The problems that the candidates are presented with are straightforward in regard to core knowledge but ask questions that the candidate may not be familiar with. We look forward to web searches, text messages and anything else the candidate can use.

The candidate knows if the team/company is a good fit for them.

Letting someone know who you are is complicated process that can easily take the entire time of the interview. So how do you let someone know who you are within a couple of hours and still accomplish the other goals of the interview? This is one of the hardest questions we try to answer during our interview. We start by holding the interview in our open work environment. The candidate can just look around and see how other teams are working. They can hear the discussions, and see the excitement. A few feet away a team is working to solve problems and tackling goals.

Our interview process is part of our work. It is collaborative and social, designed to mimic the best parts of our work while still being an interview. Teammates take turns typing, helping, and guiding during the process, all of this helps give a feeling of what to expect.

If the candidate seems to be a good fit skill-wise, we then continue to a Lean Coffee session that lasts 45 minutes to an hour. This changes how the Q&A process as it starts by putting all questions and topics up front for all to see. Even if all topics are not discussed, the candidate and the team can see what was on each other’s mind.

A Lean Coffee format gives the candidate the chance in participating in the selection of questions and topics. Each person participating in the interview has three dots to vote on topics. These topics are then organized by number of votes. The topics with the most interest are then discussed first.

This gives the candidate a lot of agency in guiding the discussion. Their voice gets heard and they get a chance to have their questions addressed. It also allows them to focus on topics from the interviewer that they feel will make them sound better.

Each topic is given a five-minute window to be discussed. When the time is over, everyone votes on continuing or moving on. If even one person wishes to continue then the topic is continued, but only for two minutes. Then the voting cycle continues until everyone is done with the topic.

Each topic discussed is a topic not a question. Everyone is encouraged to reflect on the topic and address what it means for them. For instance, if the topic given by one of the interviewers is, “Describe a moment when you felt you really shined,” all members of the interview are encouraged to answer, not just the candidate.

This also means that topics brought up by the candidate will not only be addressed by the interviewers, but also by the candidate.

These discussions are the best way that we have found to truthfully let the candidate know who we are, what we do and why we do it.

In Summary

The Hunter Software Development Group has a very different approach to interviewing born out of a different perspective. We start with a foundation of kindness, consideration and respect and build from there.

We work to fairly assess the candidate based off of four types of skills. Emotional intelligence, unique experiences, what makes the candidate shine and what they know about Extreme Programming.

These methods have been very successful for us when hiring. We retrospect and adapt after every interview, so we are always improving. However, I would like to be part of a larger conversation. By discussing this with other professionals the community as a whole can gain insight from each other’s experiences that might not be seen any other way. Maybe the whole industry can improve and find yet to be discovered better ways. Mob Programming has led to better code quality. If we all huddle up and analyze how we interview who knows what will happen?

A Kata Deep Dive Part 3

A continuation

This article follows, A Kata Deep Dive Part 2 and you will have needed to read it to continue.

Where were we?

We just finished refactoring our tests into a combinitory test. The current test suite should look like:

   1:      [TestClass]
   2:      [UseReporter(typeof(DiffReporter))]
   3:      public class TicTacToeShould
   4:      {
   5:          // The first player decides to be X or O
   6:          // The game starts with an empty 3 x 3 board
   7:          // Play alternates between X and O
   8:          // A win is decided by the first of X or O that gets 3 in a row, column, or diagonal
   9:          // A tie is determined if there is no winning move by either X or O
  10:   
  11:          [TestMethod]
  12:          public void StartWithAnEmpty3By3Board()
  13:          {
  14:              var game = new Game();
  15:              Approvals.Verify(game);
  16:          }
  17:   
  18:          [TestMethod]
  19:          public void FirstMoveEitherXorOInAllLocations()
  20:          {
  21:              var locations = new[] {GridLocations.TopLeft, GridLocations.BottomRight, };
  22:              var markers = new[] {"X", "O"};
  23:              CombinationApprovals.VerifyAllCombinations((marker, location) =>
  24:              {
  25:                  var game = new Game(marker);
  26:                  game.Move(location);
  27:                  return Environment.NewLine + game;
  28:              }, markers, locations);
  29:          }
  30:      }

We also have an Enum:
 
   1:      public enum GridLocations
   2:      {
   3:          TopLeft,
   4:          BottomRight,
   5:      }

And our Logic:
 
   1:      public class Game
   2:      {
   3:          private readonly string _firstMove;
   4:          private string _topLeft = " ";
   5:          private string _bottomRight = " ";
   6:   
   7:          public Game(string firstMove = "X")
   8:          {
   9:              _firstMove = firstMove;
  10:          }
  11:   
  12:          public override string ToString()
  13:          {
  14:              return $@" {_topLeft} |   |   
  15:  ---+---+---
  16:     |   |   
  17:  ---+---+---
  18:     |   | {_bottomRight} 
  19:  ";
  20:          }
  21:   
  22:          public void Move(GridLocations location)
  23:          {
  24:              if (location == GridLocations.TopLeft)
  25:              {
  26:                  _topLeft = _firstMove;
  27:              }
  28:              else
  29:              {
  30:                  _bottomRight = _firstMove;
  31:              }
  32:          }
  33:      }

Time for a design change

So the next test would be a new location. Something like "GridLocations.TopMiddle" but before I get to that I see a refactoring that can happen. I am using an Enum to represent discrete pieces of related domain knowledge, particularly the locations a spot can exist. I am about to add a 3rd location to that Enum, and now I must ask if I am using the correct abstraction. An Enum is a language primitive substituting for a domain primitive.

I want something called a "Tagged Union" or "Discriminating Union" to better represent my locations. The problem with an Enum, is that they are implemented as integers. I can pass any integer to my method cast as the Emum "GridLocations". This does not accurately represent my domain. So I will refactor my Enum into a virtual class with private inheritors and singleton objects.

   1:      public abstract class GridLocations
   2:      {
   3:          private class TopLeftClass : GridLocations { }
   4:          private class BottomRightClass : GridLocations { }
   5:   
   6:          public static GridLocations TopLeft { get; } = new TopLeftClass();
   7:          public static GridLocations BottomRight { get; } = new BottomRightClass();
   8:      }

The tests now fail, so our implementation is not correct. We need to fix the "ToString" method on each of the classes.

\

The code should look like:

   1:      public abstract class GridLocations
   2:      {
   3:          private class TopLeftClass : GridLocations {
   4:              public override string ToString()
   5:              {
   6:                  return "Top Left";
   7:              }
   8:          }
   9:          private class BottomRightClass : GridLocations {
  10:              public override string ToString()
  11:              {
  12:                  return "Bottom Right";
  13:              }
  14:          }
  15:   
  16:          public static GridLocations TopLeft { get; } = new TopLeftClass();
  17:          public static GridLocations BottomRight { get; } = new BottomRightClass();
  18:      }

I chose to break my tests by adding a space between the camel hump identifiers because I want to favor non-programmer readability in my output.


That looks a lot better. Copy the left to the right and re-run all the tests. Everything should pass.

The next location

So now we add locations to the "locations" collection in our test. I will add "TopMiddle" to my collection.

   1:          [TestMethod]
   2:          public void FirstMoveEitherXorOInAllLocations()
   3:          {
   4:              var locations = new[] 
   5:              {
   6:                  GridLocations.TopLeft, GridLocations.TopMiddle,
   7:                  GridLocations.BottomRight,
   8:              };
   9:              var markers = new[] {"X", "O"};
  10:              CombinationApprovals.VerifyAllCombinations((marker, location) =>
  11:              {
  12:                  var game = new Game(marker);
  13:                  game.Move(location);
  14:                  return Environment.NewLine + game;
  15:              }, markers, locations);
  16:          }

I need to implement "TopMiddle" so that it will compile.

   1:      public abstract class GridLocations
   2:      {
   3:          // ...
   4:          private class TopMiddleClass : GridLocations
   5:          {
   6:              public override string ToString()
   7:              {
   8:                  return "Top Middle";
   9:              }
  10:          }
  11:   
  12:          public static GridLocations TopLeft { get; } = new TopLeftClass();
  13:          public static GridLocations TopMiddle { get; } = new TopMiddleClass();
  14:          // ...
  15:      }

Now we have 2 failures for the wrong reason.



We are not expecting or receiving the right thing. We need fix our expectations.



With this test failing for the right reason we can now update the logic.

   1:      public class Game
   2:      {
   3:          private readonly string _firstMove;
   4:          private string _topLeft = " ";
   5:          private string _bottomRight = " ";
   6:          private string _topMiddle = " ";
   7:   
   8:          public Game(string firstMove = "X")
   9:          {
  10:              _firstMove = firstMove;
  11:          }
  12:   
  13:          public override string ToString()
  14:          {
  15:              return $@" {_topLeft} | {_topMiddle} |   
  16:  ---+---+---
  17:     |   |   
  18:  ---+---+---
  19:     |   | {_bottomRight} 
  20:  ";
  21:          }
  22:   
  23:          public void Move(GridLocations location)
  24:          {
  25:              if (location == GridLocations.TopLeft)
  26:              {
  27:                  _topLeft = _firstMove;
  28:              }
  29:              else if (location == GridLocations.TopMiddle)
  30:              {
  31:                  _topMiddle = _firstMove;
  32:              }
  33:              else
  34:              {
  35:                  _bottomRight = _firstMove;
  36:              }
  37:          }
  38:      }

Everything should pass again. Now we are left with more cleanup. We have a nasty looking if block, we also have some magic strings. I think I am going to end it here as there is a LOT more that can be done but I feel as if I have started you on a path.

Thank you for your time.

Thank you http://www.manoli.net/csharpformat/ as it helped me format all my code.

A Kata Deep Dive Part 2

Part 2

This is a continuation of A Kata Deep Dive and you must have read that to continue here.

Where did we leave off?

I was walking you through the Kata for Tic Tac Toe and gotten to where we can have an opening move on either the top left or lower right. However, we had a failing test.


We were expecting a 'O' in the upper left but were getting an 'X' instead. To fix that I will need to fix the new "Move" method.

   1:          public void Move(GridLocations location)
   2:          {
   3:              if (location == GridLocations.TopLeft)
   4:              {
   5:                  _marker = _firstMove;
   6:              }
   7:              else
   8:              {
   9:                  _bottomRight = _firstMove;
  10:              }
  11:          }

Now our tests are passing.


There is however more cleaning to be done. We have an extra "Move" method now and the "_marker" field is misnamed. Lets start with that extra method. If we delete the version of "Move" that takes no parameters now it nothing should break. Then we can rename "_marker" to "_topLeft".

Our tests should look like:

   1:      [TestClass]
   2:      [UseReporter(typeof(DiffReporter))]
   3:      public class TicTacToeShould
   4:      {
   5:          // The first player decides to be X or O
   6:          // The game starts with an empty 3 x 3 board
   7:          // Play alternates between X and O
   8:          // A win is decided by the first of X or O that gets 3 in a row, column, or diagonal
   9:          // A tie is determined if there is no winning move by either X or O
  10:   
  11:          [TestMethod]
  12:          public void StartWithAnEmpty3By3Board()
  13:          {
  14:              var game = new Game();
  15:              Approvals.Verify(game);
  16:          }
  17:   
  18:          [TestMethod]
  19:          public void FirstMoveXToTopLeft()
  20:          {
  21:              var game = new Game();
  22:              game.Move(GridLocations.TopLeft);
  23:              Approvals.Verify(game);
  24:          }
  25:   
  26:          [TestMethod]
  27:          public void FirstMoveOToTopLeft()
  28:          {
  29:              var game = new Game(firstMove: "O");
  30:              game.Move(GridLocations.TopLeft);
  31:              Approvals.Verify(game);
  32:          }
  33:   
  34:          [TestMethod]
  35:          public void FirstMoveXToBottomRight()
  36:          {
  37:              var game = new Game();
  38:              game.Move(GridLocations.BottomRight);
  39:              Approvals.Verify(game);
  40:          }
  41:      }

Our game should look like:

   1:      public class Game
   2:      {
   3:          private readonly string _firstMove;
   4:          private string _topLeft = " ";
   5:          private string _bottomRight = " ";
   6:   
   7:          public Game(string firstMove = "X")
   8:          {
   9:              _firstMove = firstMove;
  10:          }
  11:   
  12:          public override string ToString()
  13:          {
  14:              return $@" {_topLeft} |   |   
  15:  ---+---+---
  16:     |   |   
  17:  ---+---+---
  18:     |   | {_bottomRight} 
  19:  ";
  20:          }
  21:   
  22:          public void Move(GridLocations location)
  23:          {
  24:              if (location == GridLocations.TopLeft)
  25:              {
  26:                  _topLeft = _firstMove;
  27:              }
  28:              else
  29:              {
  30:                  _bottomRight = _firstMove;
  31:              }
  32:          }
  33:      }

We are left with duplication in our tests. The test methods "FirstMoveXToTopLeft", "FirstMoveOToTopLeft", and "FirstMoveXToBottomRight" all look pretty similar. We can reduce this duplication by using a combinatory verification.

A combinatory verification takes combinations of inputs and verifies all possible outputs. This is made easy with the ApprovalTests Nuget library.

A new kind of test


   1:          [TestMethod]
   2:          public void FirstMoveEitherXorOInAllLocations()
   3:          {
   4:              // Arrange: Create a collection of Locations That include only TopLeft
   5:              //          Create a collection of markers that include only X
   6:              // Verify: A new board created with the marker from the collection of markers as the first player.
   7:              //         With a move from the collection of locations
   8:              //         Has the correct piece in the correct location.
   9:          }

The comments are a bit more verbose. This is because this is a more complicated kind of test. I will implement from the bottom up again. And take smaller steps.

   1:          [TestMethod]
   2:          public void FirstMoveEitherXorOInAllLocations()
   3:          {
   4:              // Arrange: Create a collection of Locations That include only TopLeft
   5:              //          Create a collection of markers that include only X
   6:              // Verify: A new board created with the marker from the collection of markers as the first player.
   7:              CombinationApprovals.VerifyAllCombinations((marker, location) =>
   8:              {
   9:                  var game = new Game(marker);
  10:              //         With a move from the collection of locations
  11:                  game.Move(location);
  12:              //         Has the correct piece in the correct location
  13:                  return game.ToString();
  14:              }, markers, locations);
  15:          }

I am using a lambda that takes 2 arguments "marker", and "location". These will be provided by the non existent collections "markers" and "locations".

   1:          [TestMethod]
   2:          public void FirstMoveEitherXorOInAllLocations()
   3:          {
   4:              // Arrange: Create a collection of locations that include only TopLeft
   5:              var locations = new[] {GridLocations.TopLeft};
   6:              //          Create a collection of markers that include only X
   7:              var markers = new[] {"X"};
   8:              // Verify: A new board created with the marker from the collection of markers as the first player.
   9:              CombinationApprovals.VerifyAllCombinations((marker, location) =>
  10:              {
  11:                  var game = new Game(marker);
  12:              //         With a move from the collection of locations
  13:                  game.Move(location);
  14:              //         Has the correct piece in the correct location
  15:                  return game.ToString();
  16:              }, markers, locations);
  17:          }

With those collections (Arrays) in place we can now run the test and see it fail for the wrong reason.


The left hand side is almost correct. It would be better if we add a new line before the game board. Lets make the right hand side correct.
[X,TopLeft] => 
 X |   |   
---+---+---
   |   |   
---+---+---
   |   |   

Now to fix the test by adding "Environment.NewLine" before the returning board.

   1:          [TestMethod]
   2:          public void FirstMoveEitherXorOInAllLocations()
   3:          {
   4:              // Arrange: Create a collection of locations that include only TopLeft
   5:              var locations = new[] {GridLocations.TopLeft};
   6:              //          Create a collection of markers that include only X
   7:              var markers = new[] {"X"};
   8:              // Verify: A new board created with the marker from the collection of markers as the first player.
   9:              CombinationApprovals.VerifyAllCombinations((marker, location) =>
  10:              {
  11:                  var game = new Game(marker);
  12:              //         With a move from the collection of locations
  13:                  game.Move(location);
  14:              //         Has the correct piece in the correct location
  15:                  return Environment.NewLine + game;
  16:              }, markers, locations);
  17:          }

Now the test passes. Time to clean up. We can start by removing those comments. Also, the test "FirstMoveXToTopLeft" is redundant. So let's delete it. Now our tests look like:

   1:      [TestClass]
   2:      [UseReporter(typeof(DiffReporter))]
   3:      public class TicTacToeShould
   4:      {
   5:          // The first player decides to be X or O
   6:          // The game starts with an empty 3 x 3 board
   7:          // Play alternates between X and O
   8:          // A win is decided by the first of X or O that gets 3 in a row, column, or diagonal
   9:          // A tie is determined if there is no winning move by either X or O
  10:   
  11:          [TestMethod]
  12:          public void StartWithAnEmpty3By3Board()
  13:          {
  14:              var game = new Game();
  15:              Approvals.Verify(game);
  16:          }
  17:   
  18:          [TestMethod]
  19:          public void FirstMoveOToTopLeft()
  20:          {
  21:              var game = new Game(firstMove: "O");
  22:              game.Move(GridLocations.TopLeft);
  23:              Approvals.Verify(game);
  24:          }
  25:   
  26:          [TestMethod]
  27:          public void FirstMoveXToBottomRight()
  28:          {
  29:              var game = new Game();
  30:              game.Move(GridLocations.BottomRight);
  31:              Approvals.Verify(game);
  32:          }
  33:   
  34:          [TestMethod]
  35:          public void FirstMoveEitherXorOInAllLocations()
  36:          {
  37:              var locations = new[] {GridLocations.TopLeft};
  38:              var markers = new[] {"X"};
  39:              CombinationApprovals.VerifyAllCombinations((marker, location) =>
  40:              {
  41:                  var game = new Game(marker);
  42:                  game.Move(location);
  43:                  return Environment.NewLine + game;
  44:              }, markers, locations);
  45:          }
  46:      }

So let's add 'O' to the markers list. The test fails but the result is good. Copy the left to the right and re-run the test.


Once that test is passing, we now have a new redundant test. We can delete "FirstMoveOToTopLeft". Now is the time to add "BottomRight" to the "locations" collection.

   1:          [TestMethod]
   2:          public void FirstMoveEitherXorOInAllLocations()
   3:          {
   4:              var locations = new[] {GridLocations.TopLeft, GridLocations.BottomRight, };
   5:              var markers = new[] {"X", "O"};
   6:              CombinationApprovals.VerifyAllCombinations((marker, location) =>
   7:              {
   8:                  var game = new Game(marker);
   9:                  game.Move(location);
  10:                  return Environment.NewLine + game;
  11:              }, markers, locations);
  12:          }

When the test is run now, you will have 2 failures.


However they look correct, so let's copy the left side to the right side and run the tests again. They should pass. Now we have 1 more redundant test. "FirstMoveXToBottomRight" can be deleted. We also proved that you can have 'O' on the first move in the lower right.

Our tests should now look like:

   1:      [TestClass]
   2:      [UseReporter(typeof(DiffReporter))]
   3:      public class TicTacToeShould
   4:      {
   5:          // The first player decides to be X or O
   6:          // The game starts with an empty 3 x 3 board
   7:          // Play alternates between X and O
   8:          // A win is decided by the first of X or O that gets 3 in a row, column, or diagonal
   9:          // A tie is determined if there is no winning move by either X or O
  10:   
  11:          [TestMethod]
  12:          public void StartWithAnEmpty3By3Board()
  13:          {
  14:              var game = new Game();
  15:              Approvals.Verify(game);
  16:          }
  17:   
  18:          [TestMethod]
  19:          public void FirstMoveEitherXorOInAllLocations()
  20:          {
  21:              var locations = new[] {GridLocations.TopLeft, GridLocations.BottomRight, };
  22:              var markers = new[] {"X", "O"};
  23:              CombinationApprovals.VerifyAllCombinations((marker, location) =>
  24:              {
  25:                  var game = new Game(marker);
  26:                  game.Move(location);
  27:                  return Environment.NewLine + game;
  28:              }, markers, locations);
  29:          }
  30:      }

Continue on to Part 3.

Thank you http://www.manoli.net/csharpformat/ as it helped me format all my code.

A Kata Deep Dive

Introduction

In discussion about using coding Katas as a way to unify knowledge across our growing team, I realized I approached them differently than the rest of my team. So I decided to write about one Kata in particular. The Tic Tac Toe Kata.

Here I present you with a step by step guide to Tic Tac Toe.

What is a Code Kata?

A Code Kata is a simple exercise designed to enforce and teach good coding practices. I have found that doing Katas has many benefits, but will focus on the main intent: Learning Good Practices.

The Kata

The Kata is Tic Tac Toe. The idea is to make an API, that facilitates the playing of the game. You can then take to computerized players, and tournaments, however I will be only taking to the point of an API.

Let's Set our Environment

For this Kata I will be Using Microsoft's language C# version 6 with Dot Net Framework 4.5.2. My editor will be Visual Studio, and my testing framework will be Microsoft's Testing Framework. I will also be using ApprovalTests Nuget Package for verification of complicated state. I will also be using Beyond Compare as my file comparison tool. There are free options that can be investigated.

When do we refactor?

I will be using a simple set of rules that will guide my design.
  1. I will use technique known as coding by intention. I will pretend everything I need already exists and create it to fulfill the need.
  2. I will always use the simplest way to make all current tests pass, not worrying about future ones.
  3. I will refactor to reduce typing.
  4. I will refactor to increase readability.
  5. I will refactor to remove duplication. If a piece of code  is duplicated 3 times if must be refactored, if I see a way to do it.
  6. I will refactor to give better adherence to the domain rules.

Let's define our domain.

In our test class we document our rules as comments. The rules I am using are:
  1. The first player decides to be X or O
  2. The game starts with an empty 3 x 3 board
  3. Play alternates between X and O
  4. A win is decided by the first of X or O that gets 3 in a row, column, or  diagonal
  5. A tie is determined if there is no winning move by either X or O


   1:  using System;
   2:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   3:   
   4:  namespace TicTacToe
   5:  {
   6:      [TestClass]
   7:      public class TicTacToeShould
   8:      {
   9:          // The first player decides to be X or O
  10:          // The game starts with an empty 3 x 3 board
  11:          // Play alternates between X and O
  12:          // A win is decided by the first of X or O that gets 3 in a row, column, or diagonal
  13:          // A tie is determined if there is no winning move by either X or O
  14:      }
  15:  }

Where do I start?

Rule 1 is naturally where I want to start: The first player decides to be X or O
The problem is that there is no context to that rule yet. What is a player? What are X and O? How is that  choice made?

So let's start instead with Rule 2:  The game starts with an empty 3 x 3 board

The first thing I need to do is setup ApprovalTests to display the results when a test fails. I will do this by adding the UseReporter Attribute to my test class.
   6:      [TestClass]
   7:      [UseReporter(typeof(DiffReporter))]
   8:      public class TicTacToeShould

Now to build my failing test for an empty board. I start with comments explaining in English (or native language) what I am trying to accomplish.

   1:          [TestMethod]
   2:          public void StartWithAnEmpty3by3Board()
   3:          {
   4:              // Arrange: create a new game
   5:              // Verify: that the game is in a state of an empty board, consisting of a 3 x 3 grid
   6:          }

I translate from the bottom up, showing intention even before items are compiling.

   1:          [TestMethod]
   2:          public void StartWithAnEmpty3by3Board()
   3:          {
   4:              // Arrange: create a new game
   5:              // Verify: that the game is in a state of an empty board, consisting of a 3 x 3 grid
   6:              Approvals.Verify(game);
   7:          }

As I add detail, I get closer to compiling.

 
   1:          [TestMethod]
   2:          public void StartWithAnEmpty3by3Board()
   3:          {
   4:              // Arrange: create a new game
   5:              var game = new Game();
   6:              // Verify: that the game is in a state of an empty board, consisting of a 3 x 3 grid
   7:              Approvals.Verify(game);
   8:          }

Finally it compiles:

 
   1:      public class Game
   2:      {
   3:      }

But when I run the test, the test fails for the wrong reason. The image on the text on the left is what we are getting, the text on the right is what we are expecting. We have not setup what we expect, so we are failing for the wrong reason.


 
We want to setup our expected so that is matches our description of a 3 x 3 grid. I will us a bit of ASCII art:

   |   |   
---+---+---
   |   |   
---+---+---
   |   |   

In  the diff tool it will look like:

 

Now it fails for the right reason.

 

So now to make it pass.

Approvals uses the object's "ToString" method to determine what to output. So the simplest way to make it work is to hard code the "ToString" method.

   1:      public class Game
   2:      {
   3:          public override string ToString()
   4:          {
   5:              return @"   |   |   
   6:  ---+---+---
   7:     |   |   
   8:  ---+---+---
   9:     |   |   
  10:  ";
  11:          }
  12:      }



Now we clean up and do any refactoring. As it is our first test, I do not see a need for any refactoring, but we can clean up our test and remove redundant comments.

   1:          [TestMethod]
   2:          public void StartWithAnEmpty3By3Board()
   3:          {
   4:              var game = new Game();
   5:              Approvals.Verify(game);
   6:          }

What is the next test?

That is always the question. Well, we have proven we have an empty board, so let's think about a test that violates having an empty board. The first move will make it so we no longer have an empty board.

I will make the assumption that the player playing the first move is 'X' as it is the most common first move. Don't worry about this invalidating rule 1, I will get to that later.


   1:          [TestMethod]
   2:          public void FirstMoveXToTopLeft()
   3:          {
   4:              // Arrange: create a new game
   5:              // Act: move to top left
   6:              // Verify: that top left spot has an 'X'
   7:          }

Let's translate those comments starting at the bottom.

 
   1:          [TestMethod]
   2:          public void FirstMoveXToTopLeft()
   3:          {
   4:              // Arrange: Create a new game
   5:              var game = new Game();
   6:              // Act: Move to top left.
   7:              game.Move();
   8:              // Verify: That top left spot has an 'X'
   9:              Approvals.Verify(game);
  10:          }

You will notice that the method "Move" does not yet exist. Let's fix that.
 
   1:      public class Game
   2:      {
   3:          public override string ToString()
   4:          {
   5:              return @"   |   |   
   6:  ---+---+---
   7:     |   |   
   8:  ---+---+---
   9:     |   |   
  10:  ";
  11:          }
  12:   
  13:          public void Move()
  14:          {
  15:          }
  16:      }

Right now it doesn't do much, but we will let our tests tell us that. Speaking of which let's run them.
Again the test fails for the wrong reason.



We need the right-hand side to show a grid with an 'X' in the upper left. Lets add some more ASCII art:
 X |   |   
---+---+---
   |   |   
---+---+---
   |   |   

Save the file and now it fails for the correct reason.


Now we need to fix our code so that all the test cases pass. The easiest way to do this is to have a marker variable that gets set to 'X' when the move method is called.

   1:      public class Game
   2:      {
   3:          private string _marker = " ";
   4:   
   5:          public override string ToString()
   6:          {
   7:              return $@" {_marker} |   |   
   8:  ---+---+---
   9:     |   |   
  10:  ---+---+---
  11:     |   |   
  12:  ";
  13:          }
  14:   
  15:          public void Move()
  16:          {
  17:              _marker = "X";
  18:          }
  19:      }

Now the tests are passing.


Let's clean up. I do not see any need to refactor yet, so let's delete those comments in the test.

What is the next test?

Now we are in an interesting place. We need a test that invalidates our current assumptions and fails a test. We can either test that the first move can be an 'O' or we can test that a second move is possible. Both are interesting. I flipped a coin and decided to go with proving that the first player can be 'O'.

   1:          [TestMethod]
   2:          public void FirstMoveOToTopLeft()
   3:          {
   4:              // Arrange: create a new game
   5:              // Act: choose O as first player
   6:              //      Move to top left
   7:              // Verify: that 'O' is in the top left of the board
   8:          }

Again I translate starting with the bottom comment.
 
   1:          [TestMethod]
   2:          public void FirstMoveOToTopLeft()
   3:          {
   4:              // Arrange: create a new game
   5:              var game = new Game();
   6:              // Act: choose 'O' as first player
   7:              game.ChooseFirstPlayerToBeO();
   8:              //      move to top left
   9:              game.Move();
  10:              // Verify: that 'O' is in the top left of the board
  11:              Approvals.Verify(game);
  12:          }

You will notice how "ChooseFirstPlayer" is first of all not implemented, and how it very closely matches the comments. This is intentional. Let's implement the method.

   1:      public class Game
   2:      {
   3:          private string _marker = " ";
   4:   
   5:          public override string ToString()
   6:          {
   7:              return $@" {_marker} |   |   
   8:  ---+---+---
   9:     |   |   
  10:  ---+---+---
  11:     |   |   
  12:  ";
  13:          }
  14:   
  15:          public void Move()
  16:          {
  17:              _marker = "X";
  18:          }
  19:   
  20:          public void ChooseFirstPlayerToBeO()
  21:          {
  22:          }
  23:      }

Again we have a failing test, but for the wrong reason. We need to configure the test to fail for the right reason:
 O |   |   
---+---+---
   |   |   
---+---+---
   |   |   

Once it is failing for the right reason we need to implement the code to show it passing.

   1:      public class Game
   2:      {
   3:          private string _marker = " ";
   4:   
   5:          public override string ToString()
   6:          {
   7:              return $@" {_marker} |   |   
   8:  ---+---+---
   9:     |   |   
  10:  ---+---+---
  11:     |   |   
  12:  ";
  13:          }
  14:   
  15:          public void Move()
  16:          {
  17:              if (_marker == " ")
  18:              {
  19:                  _marker = "X";
  20:              }
  21:          }
  22:   
  23:          public void ChooseFirstPlayerToBeO()
  24:          {
  25:              _marker = "O";
  26:          }
  27:      }

Now we have a lot to clean up. First let's delete those redundant comments. Once those are gone we look at our new test and we see a bit of temporal coupling on line 5. We have to set the first call "ChooseFirstPlayerToBeO" before we make our first move if we want our first move to be 'O'.

   1:          [TestMethod]
   2:          public void FirstMoveOToTopLeft()
   3:          {
   4:              var game = new Game();
   5:              game.ChooseFirstPlayerToBeO();
   6:              game.Move();
   7:              Approvals.Verify(game);
   8:          }

This coupling is nasty because there is no inherent tie between "ChooseFirstPlayerToBeO" and the first move. Secondly, once the first move is made, this method has no real meaning.

Fortunately coupling like this has a predefined way to make the coupling clear. There is a standard way to setup our environment to ensure that everything is correct. That would be the constructor. If we refactor this dependency into the constructor it cleans up and makes sense.

Here is what the test looks like now.

   1:          [TestMethod]
   2:          public void FirstMoveOToTopLeft()
   3:          {
   4:              var game = new Game(firstMove: "O");
   5:              game.Move();
   6:              Approvals.Verify(game);
   7:          }

And you can see that the logic simplified also by removing the need for the "If" in the move method.

   1:      public class Game
   2:      {
   3:          private readonly string _firstMove;
   4:          private string _marker = " ";
   5:   
   6:          public Game(string firstMove = "X")
   7:          {
   8:              _firstMove = firstMove;
   9:          }
  10:   
  11:          public override string ToString()
  12:          {
  13:              return $@" {_marker} |   |   
  14:  ---+---+---
  15:     |   |   
  16:  ---+---+---
  17:     |   |   
  18:  ";
  19:          }
  20:   
  21:          public void Move()
  22:          {
  23:              _marker = _firstMove;
  24:          }
  25:      }

The Next First Move

Having tackled the fact that the first move can be either X or O as long as it is in the "Top Left" what happens if I want to move to "Bottom Right" instead? Lets write that test. We will start with X.

   1:          [TestMethod]
   2:          public void FirstMoveXToBottomRight()
   3:          {
   4:              // Arrange: create a new game
   5:              // Act: move to Bottom Right
   6:              // Verify: that only the bottom right has an 'X'
   7:          }

I translate bottom up again, though I now have a problem with my API.

   1:          [TestMethod]
   2:          public void FirstMoveXToBottomRight()
   3:          {
   4:              // Arrange: Create a new game
   5:              var game = new Game();
   6:              // Act: Move to Bottom Right
   7:              game.Move("Bottom Right");
   8:              // Verify: that only the bottom right has an 'X'
   9:              Approvals.Verify(game);
  10:          }

The move method does not take a parameter. My first instinct is to use a string, but looking over the tests I already have, I know I want intellisense to help me out. Before going on, I am going to change my API to use an Enum type.

   1:          [TestMethod]
   2:          public void FirstMoveXToBottomRight()
   3:          {
   4:              // Arrange: Create a new game
   5:              var game = new Game();
   6:              // Act: Move to Bottom Right
   7:              game.Move(GridLocations.BottomRight);
   8:              // Verify: that only the bottom right has an 'X'
   9:              Approvals.Verify(game);
  10:          }

The Enum "GridLocations" does not exist yet. So let's fix that.

 
   1:      public enum GridLocations
   2:      {
   3:          BottomRight
   4:      }

The method "Move" still does not take a "GridLocations" so we need to add it. We will add it first with an overload and then refactor our tests to simplify our implementation.
   1:          public void Move()
   2:          {
   3:              _marker = _firstMove;
   4:          }
   5:   
   6:          public void Move(GridLocations location)
   7:          {
   8:          }

Now we need to make the test fail for the right reason.
   |   |   
---+---+---
   |   |   
---+---+---
   |   | X 

Once that is done we are ready to implement.

   1:      public class Game
   2:      {
   3:          private readonly string _firstMove;
   4:          private string _marker = " ";
   5:          private string _bottomRight = " ";
   6:   
   7:          public Game(string firstMove = "X")
   8:          {
   9:              _firstMove = firstMove;
  10:          }
  11:   
  12:          public override string ToString()
  13:          {
  14:              return $@" {_marker} |   |   
  15:  ---+---+---
  16:     |   |   
  17:  ---+---+---
  18:     |   | {_bottomRight} 
  19:  ";
  20:          }
  21:   
  22:          public void Move()
  23:          {
  24:              _marker = _firstMove;
  25:          }
  26:   
  27:          public void Move(GridLocations location)
  28:          {
  29:              _bottomRight = "X";
  30:          }
  31:      }

Now we are in a great place to clean up our code. Lets start by deleting those comments in the test. Then we are going to alter one of our prior tests to use the new "Move" method. We will start with "FirstMoveXToTopLeft".

 
   1:          [TestMethod]
   2:          public void FirstMoveXToTopLeft()
   3:          {
   4:              var game = new Game();
   5:              game.Move(GridLocations.TopLeft);
   6:              Approvals.Verify(game);
   7:          }

So we don't have a "TopLeft" as part of our Enum type. We will now add it.

   1:      public enum GridLocations
   2:      {
   3:          TopLeft,
   4:          BottomRight,
   5:      }

Of course now our test fails. We expected 'X' in the upper left and now it is in the lower right. Let's fix that with a simple if statement.



   1:          public void Move(GridLocations location)
   2:          {
   3:              if (location == GridLocations.TopLeft)
   4:              {
   5:                  _marker = "X";
   6:              }
   7:              else
   8:              {
   9:                  _bottomRight = "X";
  10:              }
  11:          }

With that the tests are now passing again.


Now we need to edit "FirstMoveOToTopLeft" to use the new "Move" method.

   1:          [TestMethod]
   2:          public void FirstMoveOToTopLeft()
   3:          {
   4:              var game = new Game(firstMove: "O");
   5:              game.Move(GridLocations.TopLeft);
   6:              Approvals.Verify(game);
   7:          }

Here everything compiles, let's see it run. We are now failing for a good reason. We expect 'O' in the upper left but are now getting 'X'.


Let's fix that in the next installment.

Thank you http://www.manoli.net/csharpformat/ as it helped me format all my code.

Why I believe in #NoEstimates

Before I start, as I will be talking about different work experiences, I need to state all my opinions are my own. They do not represent the opinions of my current or past employers.

 

That being said now let me begin.

 

What:

When I was first introduced to the concept of #NoEstimates I was a mid-level developer and thought that it was a wacky idea that could never work. Later, still a mid-level developer, I decided that working with estimates was stupid. Then I grew up and learned that the world was not black and white. I listened to what @WoodyZuill had to say and tried to understand the why and how of #NoEstimates.

Experimentation:

My first experiences with trying #NoEstimates had nothing to do with Woody. I worked in a small company that hired me to take over a legacy VB.Net v1 project which had failed so badly they fired the whole team. They had no source control despite having 13 versions of the application deployed, and only one copy of official source code that didn’t match any of the deployed versions. I hired a new team, we focused on fixing bugs that were discreet, understandable and easily repeatable.

We gave no promises and made #NoEstimates. We focused on discovering value, by giving users fixes to things that were easily understandable. Within 3 months not only did we have source control, we also managed to reduce the number of variant applications and we were deploying every week. We had moved beyond bug fixes to new features and enhancements.

We were so successful, that the company sold in under 2 years. The CEO was able to retire, based on the value we delivered. We did this entirely without estimates.

Tutelage:

Later, I got to experience #NoEstimates in a completely different way. The team I was part of worked on custom line of business applications. We often produced software for different departments within the company. Here we focused on changing discussions that were given to us. Typically we were given a document with all of the requirements on it. Instead of trying to eat the elephant in one bite, we would ask, “What is one thing that if we gave it to you now would make your life better?” Taking the highest priority issue we would refine it to figure out the specific functionality that we could produce which had the qualities of being discrete, understandable and definable.

Once arrived on the story, we would work to deliver it. Once it was delivered, we would follow up with the users to see that it indeed had met their need. If it didn’t, we changed it. When the need was met correctly, we were told what the next need was.

That is how we worked. The company never had worry about interrupting us, because our deliverables ended up taking less than a couple of days on average. They were willing to wait for the next feature because they knew it wouldn’t take long for the current one to be finished. This was not a precondition, or intentional. It happened because of the attributes by which we isolated stories tended to lead to small, digestible chunks. Occasionally it would take significantly longer. That was also okay because it meant that there were more unknowns in that piece.

 

So What:

#NoEstimates as I have witnessed it accomplishes two things. The first is it moves authority to make business decisions to the current point in time. By delaying the act of what has priority, to the last responsible minute the business is better able to cope with business as it is.

The second benefit is that it places business decisions in the hands of those who have the knowledge to make the decision. I always say that programmers are business people who have not been correctly trained in business. I say that because every line of code is a decision about how the company does business. By focusing on discrete deliverable chunks and using those chunks to measure value/need, a lot more of the decision of what goes into the application goes to those who are responsible for the business.

 

Now What:

#NoEstimates is the beginning, not the answer. There is a lot more exploration that can happen out there. Let’s focus on improving how we do business, and share our successes and failures. Eventually we will always find better. 

Toxicity is Abuse

Why I am writing this

This weekend I got into a lot of discussions about the responsibilities of a programmer.  I heard multiple times that a programmer cannot be held responsible if they are working in an environment that is toxic and forces bad behavior. While I do not advocate that someone threaten their ability to feed, clothe, or house themselves (or family) because of some theoretical responsibility, it is imperative to get out of a toxic environment.

This weekend I was in a conversation about a consultant that was described as abusive by the other employees and someone said: “They only fear for their jobs because they are too stupid to do the job right.” In other words, they deserved to be abused.

In another conversation, I mentioned that a programmer has a responsibility to do what is right. I was told that this was a pipe dream because of the toxicity of work environments. To me this translates as, “Offices can treat you any way they want because you are worthless.”

The funny thing is I have heard these statements before.

My mom married an advertising executive when I was 8. It turns out that he was a drug user who slowly revealed his nasty temper. I was often backhanded hard enough to knock me from my feet, and I got to watch as the same thing happened to my mom.

 I heard the whispers of neighbors and even friends.

They sounded a lot like how I now hear people talk about toxic work environments. The words are slightly different but the meanings are the same. The fault lies on the victims. If they are being abused, then they deserve it.


Tweet: Stop making it easy for for companies to be abusive. Read http://bit.ly/ToxicJobs by @JasonKerneyTweet: Stop making it easy for for companies to be abusive. Read http://bit.ly/ToxicJobs by @JasonKerney


It takes more courage, stamina and risk to stand up to an abusive person or organization than most people know. That chapter, in the end, was a small chapter of my life. My mom left that man one night and never looked back.

When we speak down on those being abused or make excuses for the abuse we make it even harder to do what is right. I implore you to stop this destructive behavior. Instead of making excuses for toxic companies, let’s do something about them.

Your responsibility

Every software developer has some professional responsibilities, even when we are unable to perform them. These responsibilities include:

·       We have a responsibility to produce bug free code.

·        We have a responsibility to produce code that is inexpensive to maintain.

·       We have a responsibility to produce value that is greater than our cost.

·       We have a responsibility to help those starting in the profession to be better at what they do.

·       We have a responsibility to share what we learn to progress the industry.

·       We have a responsibility to understand our customer’s, company’s or client’s business well enough to make informed business decisions about the software we write.

·       We have a responsibility to say ‘No’ to our employers if we are asked to do something that endangers time, profit, relations, information, reputation or money of an individual, company, community or ourselves.

·       We have a responsibility to provide value well above our cost.

 

Doing that will cost me my job!

If you are in an abusive relationship with your employer, one or more of those responsibilities become impossible to execute without being fired. That is a tough and scary place to be. I am not saying for you to risk your job, and risk being homeless.

What I am saying is that you do have a responsibility to leave. Don’t quit your job without a new one. Look for help within the community.

Then share what you learn. Help the community understand what you did to find a good place to work. This will give hope to those who are in similar situations.

We need to use economic power to stop abuse.

These abuses are not illegal. They are immoral, but that does not give us any legal ground to prevent them.

Companies need to make at least 3x their operating costs to be successful. That means that a company sees at least 3x profit from your pay. YOU ARE WORTH A LOT MORE THAN YOU ARE BEING PAID! We have value. In today’s economy custom software makes and breaks a company.

If a toxic company could not keep their employees or better yet not be able to hire then they will not be able to compete against non-toxic companies. The problem now is that programmers stay in toxic situations. This allows toxic companies to compete.

Let’s stop this. Leave those companies. Leave them as soon as you realize they are toxic. Abandon them, and move to companies that are doing it correctly.


Tweet: I once left a toxic company. bit.ly/ToxicJobs @JasonKerneyTweet: I once left a toxic company. bit.ly/ToxicJobs @JasonKerney

Transformational Communication

Intro:

I recently came across a framework for discussing and categorizing the types of messages we see. I present it here to help analyze the way that the community talks about Agile. The hope is that through analysis we can improve the way we deliver our message.

I will give you the framework for analyzing our delivery that I learned. I will explain what it means when a message is hard to understand, or compromised. The hope is by seeing similarities in what we are putting out into the world the community can better self-adjust.

When I say community I include myself. I have been and am guilty of violating the rules set forth by this framework. I am no better than anyone else. In writing this blog, I have had to swallow a large pill and make the decision to change.

Framework:

Let’s assume that the goal is to deliver a message to an audience. If I examine how understandable our message is on one axis. Then we examine how intact the message is on the second axis.



So if that message, is Agile then I can diagnose why I am being ineffective in communicating what I want. If either the understandability of what I am saying or content of what I am saying is low, I fail. I need to be able to communicate with the highest approachability if I am to succeed.

That is fine and easy to say, but what do I do if either or both, understandability or intact-ness is low? First you have to be able to recognize when either or both are low. I will give examples and some explanation. I will also give some reasons why something is low, with the hope of guiding you out of that position.

 

Noise

When both understandability and content are low, what you have is noise.


Noise comes in all forms. With noise we build a wall hiding the fact that there is no real content. Noise can be either ranting with no context to how and why something failed, or it can be cheerleading. Both of these turn people away from the message because it is unapproachable. If someone has concerns or excitement regarding the message you have left them with nowhere to go. All they have is how the delivery left them feeling and a bit of anxiety about its meaning.

I have been guilty of this. I have both complained that too many people call themselves Agile, without clarification as to why they are not Agile. I have also cheered the success I have had with agile techniques without giving context or information about why I had success.

The less concrete what you say is the more likely it is to be noise.

Non-contextual

When the content is intact but people are unable to understand and digest it or act on it, it is non-contextual.



Here you preserve the message by framing it into a single context. There is only one way the message can exist is within your context. If you ever find yourself talking in absolutes you are being non-contextual. This does not mean that you compromise what you are saying only you need to frame it in representation of the audience’s context.

Accommodating

When the understandability, and ability to act, are high but without the meaning or original message that is accommodating.



Accommodating starts with a message, but allows it to be adaptable to whatever interpretation the audience may have. Each person interacting with the message changes it to fit their needs. Nothing actually changes except the meaning of the message.

Here you lose your intent. Context is mistaken for reality and presumed to be the truth rather than a commonality upon which to build communications. I have been guilty of saying that everything is a suggestion without giving context to how you evaluate what is needed.

Transformational

So far I have only talked about the negative. There is one part of the graph that actually signifies success. If I can communicate such that I deliver the most of the content I was intending while making it understandable then the message is transformational.



In order for a message to be transformational, it has to be able to reach its audience and be complete. That means describing it, and explaining it with the context not only considered but understood. You can only deliver a message to someone you understand. Once you understand your audience you can help them to understand you.

Summary

We can take the way we deliver a message, Agile in this case, and analyze it to understand if it can be effective. We can also examine messages we hear and put out into the world to see how effective they are.

We examine the message by how much content there is, and how understandable it is. We can classify our communication. Noise is neither understandable nor does it actually inform. Non-contextual messages keep the context but reduce understandability by ignoring context. Accommodating messages are very clear but lose content by allowing others to change the meaning.

 

Only when we keep the message intact, and clearly deliver it from an understanding position do we become transformational.



Now what

When we talk about Agile, we are talking about transformation. We are trying to bring an industry build on the mistreatment of people and failing processes to a point of success for all. We are trying to build human systems to automate the world, drive business, and generate money.

We cannot do this if the industry does not understand us. It becomes harder if bad experiences make it so they don’t want to understand us. We need to change the way we approach this, we need to be more efficient in what we say and how we say it.

So now what? Now we retrospect and learn. We categorize our successes and failures into these four groups and attempt to capitalize the good.

Before we speak, judge, or advise; take a moment and reflect. Move those conversations to the first quadrant. Focus on the individuals’ beliefs and knowledge. Try to capture their context and drive the lessons through them. Let’s transform the world!

 

Three letters that change how you think

Solutions feel so much more comfortable then questions; don’t they? Finding a solution makes us feel good. Solutions have power and people are willing to pay real money for solutions. Questions on the other hand cause discomfort. Questions represent problems that need to be solved and cost our money a lot of times.

So it is only natural that we focus on the solution. We jump to how a problem is solved without first understanding why it needs to be solved. We risk missing critical understanding in order to feel the rush of finding the solution.

Tweet: @JasonKerney Explains why we should ask why first bit.ly/rjkblog

I am not using the empirical “we” here, I am very much including myself in that “we”. I like solutions also. I like it when I can tie a problem neatly up with a bow and hand the finished package over to solve all that ails someone.

The solution is emotionally powerful but often the why is so much more important. When we understand the why we can better engineer the solution. The solution we will provide will be the correct one, or at least one that better suites the need.

As a developer and a problem solver how is always foremost in my mind. How can I solve the problem you are having? How do I alter my code to get the desired result? How…? “How” is powerful, it speaks of solutions and gives guidance. It is also the wrong question most of the time.

I have found that the “how” of something is inconsequential most of the time. When we focus on how we optimize for the solution rather than the issues that need a solution. We start fixing before we understand what it is we are fixing. When we ask the wrong questions we get answers that do not map correctly, even when they answer the questions we are asking.

Now if we knew the correct question we could find answers that have more meaning. The problem is that the correct question is often harder to answer. When we ask why we gain understanding of the root cause. The more we know about an issue, or request the better we can address that request. Why is much more powerful because instead of answers and guidance it leads us to understanding.

How follows why, but how is often disguised. For instance, “What would you like to see on this screen instead?” is not asking “what”. It is really asking “How do you want me to solve the issue you are pointing out with this screen?” Another hidden how is: “What if I changed this?” That question is really: “Is this how I solve the problem?”

Understanding that how can be asked many ways indirectly allows us to change the conversation by refusing to be lured in. We can instead rephrase each of the above examples to why questions. “Why do you want this screen changed?” or “What is it that you are trying to solve?” (Yes this is using “What” to hide a “Why”.)

That is only half the issue. “How” is seductive. Not only do we ask “how” when instead of “why” we are often asked “how” instead of “why”. We need to listen for it, and refuse to answer it prematurely. When we are asked “how” questions we need to change the conversation to focus on why first. We need to make sure both the person asking the question, and us, understands why. Once that understanding exists then how becomes important.

So let’s lead with understanding and follow with results. That is why a three letter word can change how, I mean why you think.