If you are setting environment variables like export SITE=’awesome site’ or export PATH=/Users/steveswedler/.rbenv/shims:/Users/steveswedler/.rbenv/bin:$PATH in your .zshrc file, those variables will not be available to POW. The reason is that the .zshrc file is only loaded for interactive sessions, like when you open a terminal window. Move the necessary lines to a .zshenv file (create it if you have to) and magically, those variables will be available to POW.

Standard advice found through Google searching is to put those lines in your .powconfig file. This might work for you if you don’t want them available anywhere else, but if you need them shared (like PATH variables) .zshenv is the way to go.

I’m still a zsh noob with a lot to learn, but I hope this saves someone some trouble.

POW ZSH and Environment Variables (.zshrc vs. .zshenv)

(mis)Communication

As one who talks about being exceptional and delivering exceptional customer experience, it saddens me to say that I have committed one of the most common customer service missteps. Assuming.

A client gave me some information and I assumed it meant the deadline was no longer as hard-and-fast as originally communicated, so I took my foot off the gas and coasted to the finishline. Only to find out I was wrong. And my client was looking bad to their client which was all on me.

I was blissfully and ignorantly going along. There was no communication through this time that my client was unhappy, and no news is good new right? Wrong. They were not happy, and were stewing over it while I was completely unaware.

We are all human and in the stress and hussel of business it is too easy to take the easy road on bad habits. Regular and deliberate communication in imperative to success. And always remember the old adage: You know what happens when you assume…

Why the web software industry is broken

My recent renewed focus on consulting with Foolish Software has lead me to a very disturbing conclusion. Web software development, particularly in the consulting space (but not exclusively), is broken.

If you think of a software as a car, it has many moving parts (an ever-changing selection of parts no less) and is bound to break down or need maintenance at some point in its lifetime. What’s worse is that it’s not a production car but a custom built machine. So when the creator goes out of business or moves on (which is usually fairly quickly) you are left with something that any mechanic can understand conceptually, but the specifics exist only in the head of the original creator.

A car is easier to quote accurately; you have certain parts at specific prices, and the labor is fairly predictable. So if someone asks for a Porsche for a Toyota price it’s easy to say no. It’s also easier for the consumer to understand why they can’t get it.

However, in software it is not uncommon for people to ask for the “Porsche” at “Toyota” pricing and if they are willing to sacrifice quality they can probably find some consultant whose price is low enough that they might get it. Or at least get what they naively believe to be it.

This is because the average consumer of software development services can’t comprehend the difference between quality workmanship in software versus a hack-job. And in some cases the hack-job is good enough.

But let’s assume that quality vs price is not a real problem. Which it is, but many people will argue with me that good enough is just enough and that you deal with the other problems later. But for the sake of argument if it isn’t a problem, software development is still broken in one more profound way.

Development is mostly looked at as a transactional service and not a partnership. This is probably the biggest area of concern. When software development is transactional, the client has a budget that usually only covers a portion of the initial development costs and little else.

The salesman working the deal needs to close, so she manipulates the finer points. No paired resources. Simplest possible solution (which often is just lip service, and code for “we’ll cram it in somehow”). No testing. This leads to cut corners, no predictability, and zero documentation.

If you cut corners at the onset, it may run fine for a while, but eventually, when people actually start to use the software in a meaningful way, its deficiencies make their way to the surface, and the initial developer is no longer around.

Nobody has kept the code up-to-date or optimized anything. Back to the car analogy, nobody has changed the oil, rotated the tires, or fixed the breaks. So what happens? Breakdown, crash, panic mode, and draining expenses to fix it.

Unfortunately, the industry is built around this transactional model and is very difficult to break. Established companies have the best chance at breaking out. They have a reputation and a bankroll to allow them to be selective. To be willing to say no the bad customers and have enough momentum to attract the good ones.

A new company just starting out is trying to pay the bills any way they can. They take the crappy work knowing the damage that is likely being done, in the hopes that they can get enough business to break through that ceiling. It rarely happens. And thus there will always be crap work to grease the gears of the endless cycle.

What can be done then?

If you are a company looking to hire developers or consultants, think about how you plan to maintain things a year or two out. What will happen when your team goes away? Is the software important enough to do it right? If so, remember that software development never ends. If your business relies on custom-built software you will always be working on it.

If you plan to offer software development consulting as a service, do right by your customers. Price it right. Include everything necessary to set your customers up for success and don’t bend. Delivering crappy software for a few bucks is not a sustainable business model and while customers may say they’re OK with cutting corners, they are lying.

When the software breaks, they will call you, and you will find yourself spending weeks or even months of non-billable hours fixing stuff they agreed to neglect. Because after all, they agreed to cut corners, not to non-functioning software.

What makes a “startup” community?

Derek Neighbors wrote a blog post about the so-called “Reality of Arizona Startup Community.” Typically I agree with his perspectives on startups and community, but not today. And while I agree the Arizona startup  community sucks for the most part, I am disappointed by the apocryphal reasoning he uses.

Let’s look at his main points.

The majority of ideas being presented here are shitty”

Who cares? We put far too much stock in ideas as the criteria for investment of our time and/or money. All ideas are worthless and most start off dumb or at least way off base anyway, so the real focus should be on the people and specifically their passion for the core intent. If you want to connect people and you’re passionate about it, just because you start with a bad implementation doesn’t mean you won’t discover new direction and motivation along the way that will allow you to pivot and find a space to excel in. The important thing is being smart enough and in tune enough with the core intent. The details are inconsequential, if you adapt.

“We lack a strong pool of mentors/business professionals with a track record of bringing product to market.”

Ignorance is bliss. If you are convicted about getting your product or idea to the market you will figure it out. You will try things. Fail. Try again. And again until you get it out there. Don’t let lack of knowledge be your excuse to not do something. More often than not the experts will impart their dogmatic thinking upon you and tell you what you can’t do which will only dissuade you anyway. Do something stupid. It’s OK.

“Seed funding is a joke”

Agreed. But not for the same reasons. It is a joke because you don’t need it anyway. Let’s say that someone was willing to seed fund your idea. Without the passion and commitment necessary to do it in the absence of money, having the money won’t help you in most cases. In rare instances you might have some capital needs to get off the ground, but mostly that is just a load of crap. Bootstrap, beg, borrow, whatever. If you aren’t willing to go it alone, you are not committed/passionate enough anyway.

We are technically poor”

This is true to the extent that we don’t have a lot of successful small to medium-sized tech firms attracting talent. This is because most companies that size lack vision and the business accumen to grow. But again I ask, who cares? Technical prowess is not necessarily advantageous for startup culture, and mostly a panacea. It can help, but most ideas don’t take a PHD to get off the ground, and if you are willing to do some googling anyone can get a basic knowledge of technology.

So if these are all just excuses disguised as conventional wisdom, what is the real problem? I think it’s the fact that we aspire to be a “startup community” to begin with. That we measure ideas based on the fallacy that is the “exit strategy”. The best products do not come from people looking for an exit strategy. Let’s all aspire to be the best at what we do and to be leaders and experts in our industries. And doors will open. And the world will change. But all the talk in the world won’t help. You can’t will it to change. You have to be it.

Stay hungry. Stay Foolish.

In an effort to not just be another “me too” about the end of an era, I’ve avoided saying too much about Steve Jobs stepping down as Apple’s CEO. Don’t get me wrong, it’s not that I find the news insignificant, but I find it more personal to me than business.

I find Steve’s rise-and-fall-and-rise-again story to be extraordinary on so many levels. I never met Steve Jobs. I probably never will. I don’t own every Apple product (though I do own my share). I know he has a less-than-pleasant reputation. But I feel that Steve Jobs is a father figure of sorts to many. He may not have always been there for you, and may have taught you some hard lessons, but he always came through when it counted and gave you what you needed even though you didn’t know it.

The understanding that life is about more than money (by one of the richest people on the planet) and that quality and commitment, above all else, can lead to success is a lesson I try to remember everyday.

Two of my favorite quotes to sum up what he meant to me better than I ever could:

“Your time is limited, so don’t waste it living someone else’s life. Don’t be trapped by dogma — which is living with the results of other people’s thinking. Don’t let the noise of others’ opinions drown out your own inner voice. And most important, have the courage to follow your heart and intuition. They somehow already know what you truly want to become. Everything else is secondary.”

“Being the richest man in the cemetery doesn’t matter to me … Going to bed at night saying we’ve done something wonderful… that’s what matters to me.”

Super-simple ajaxy pagination in rails with jQuery and WillPaginate

I found myself needing to do some pretty heavy ajax for a recent project, and I needed to ajax pagination with an added twist of user defined per_page.

I looked around the web and found a bunch of ideas, but most of them were way more complex than necessary.

I was already using jQuery for my javascript library and will-paginate for pagination, so I went down the simplest route I could think of.

Firstly, I am assuming that you have a project using jquery and will_paginate, and they are installed properly.

Then, let’s say you have an index view that renders a list of products through a partial.

File: products/index.html.erb

<h1>Listing products</h1>

<div id="products-container">
  <%= render :partial => "products" %>
</div>

File: products/_products.html.erb

<table>
  <tr>
    <th>Name</th>
    <th>Description</th>
    <th>Price</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>
  <% @products.each do |product| %>
    <tr>
      <td><%= product.name %></td>
      <td><%= product.description %></td>
      <td><%= product.price %></td>
      <td><%= link_to 'Show', product %></td>
      <td><%= link_to 'Edit', edit_product_path(product) %></td>
      <td><%= link_to 'Destroy', product, :confirm => 'Are you sure?', :method => :delete %></td>
    </tr>
  <% end %>
</table>

First let’s handle the user-defined per_page attribute.

In your _products.html.erb file, add to the end:

<%= select_tag :per_page, options_for_select([10,20,50], (params[:per_page].blank? ? 20 :  params[:per_page].to_i)) %>
<%= will_paginate @products, :id => "pagination", :previous_label => "Previous", :next_label => "Next" %>

The pagination must go in the partial so that it updates when the ajax response is rendered.

Then add the javascript to index.html.rb:

<script type="text/javascript" charset="utf-8">
  <% content_for :js do %>
    // This ajaxSetup is necessary for rails recognizing format.js. Done in application.js preferably.
    jQuery.ajaxSetup({
      'beforeSend': function(xhr) {
      xhr.setRequestHeader("Accept", "text/javascript")
    }
    });

    // channel per page submit on change
    $('#per_page').live('change', function() {
      $.get(<%= products_path() %>, { per_page: $('#per_page').val()}, function(data) {
        $('#products-container').html(data);
      });
    });
  <% end %>
</script>

This assumes you have a yield :js set up in your application.html.erb file.

Now in your products_controller index action add some code to handle pagination and return something for the format.js like this:

def index
  @per_page = params[:per_page].blank? ? 20 : params[:per_page]
  @products = Product.all.paginate(:per_page => @per_page, :page => params[:page] ? params[:page] : 1)

  respond_to do |format|
    format.html # index.html.erb
    format.js { render :partial => "products" }
  end
end

At this point, if you load up the products page, you should be able to select the desired per_page number and the page should update to reflect the new pagination. However, if you click on any page, you’ll see that the page still refreshes. Let’s handle that now.

Add this javascript to index.html.erb file:

  // handle pagination links as ajax
  $('.pagination a').live('click', function(){
    $("#products-container").load( $(this).attr('href') );
    return false;
  });

That’s it. Now the page should update via ajax all smooth-like. It’s a little hacky in how I’m handling format.js to just return a partial, but in my case I have no other use for the js handler. Let me know if it works for you or if you have any questions.

Tagged , , , , , , ,

Acceptance Criteria That Doesnt’ Suck

It’s planning day, so today seemed as good as any to post about good AC.

Gathering Acceptance Criteria, or AC for short, may be the most critical component to a successful sprint. Unfortunately, it’s a predictably regular occurrence to start a sprint and somewhere along the line, the product owner finds some additional complexity or use case that doesn’t fit the planned implementation. It is also often that the product owner will not sign off on the work while the feature does not meet these newly defined expectations.

At this point, you have two choices. You can let them add this AC mid-sprint (which of course is a major no-no), or you can talk them into making a new story and then go through the hassle of explaining that this new functionality is out of scope and that they will have to de-scope some other feature blah blah, nightmare!

Anytime you discover new things during a sprint you are making your life progressively more difficult. And ultimately you are setting your project up for failure. Get it right the first time!

If you are doing TDD or at least writing cucumber tests, think of AC as a set of scenarios. The more specific the less missed AC there will be. Cucumber scenarios follow a simple pattern.

  • Given (State)
  • When (Action)
  • Then (Result)

You can have multiples of each in a scenario, but the pattern remains: given a set of criteria, when I do some action, I should get some result.

Here are some examples:

  • Given I am on X page. When I follow Y link, then I should see something.
  • Given I am on Z page. When I select “date” from dropdown list, then it should re-sort results
  • Given i am on the login page. When I fill out the login form with my email and password, then I should see the dashboard page and a welcome message.

They don’t have to use the exact language of a cucumber scenario, but using the basic formula will lead you to further questions and discovery.

In order to not waste a bunch of time in planning, be sure to work with your product owners to do their part and come to planning meetings with AC prepared.  But don’t be surprised when you have to hold their hand through it the first few times.

If the scenario is not immediately evident, or if the customer is unusually difficult, here are some AC discovery questions. This is by no means exhaustive, but we can add to it.

  1. How do I get here?
  2. What does it look like?
    • what should I see?
    • what should I not see?
    • potential options and outcomes?
  3. What happens after?
  4. Who will use it (major feature or edge use case)
  5. What can we do to simplify this?
  6. What would happen if your users did not have this feature?

Agile Product Management – It’s Real!

Product management is a dirty word in Agile software development circles, and I am baffled by this blatant omission. Considering that most people have no idea what it is, the resistance is due to ignorance and/or fear, more than a disagreement with the philosophies or methodologies of it.

Agile is incomplete without product management. As I see it, the intent of the agile methodology is to allow for emergence in the development process. But in order for emergent phenomena to occur, all participants must have two basic things; a clearly defined common goal, and a set of guiding principals by which they can evaluate all decisions.

This is precisely what product management is about.

Most of the skeptics are already rolling their eyes. I can see them. But I present to you a minimalist version that you can start implementing now and see for yourself if it’s an idea worth further exploration.

Before I start, if you are not having a kickoff meeting for new projects, you should stop reading this now and seriously reconsider your career choice.

If you are, start your meeting with these four questions to set the target. This way everyone knows what the goal is and the constraints they are working in. Constraints are very important. Knowing the constraints will help you know where the client will be willing to compromise to achieve the goal.

1. Why are we building this, and what problem are we solving?
This is the goal setting part of the process. Be clear and concise. A goal needs to be easily repeatable and easily understood by someone unfamiliar with the product.

2. Who is it for: Primary Audience? Secondary?
Define a very loose profile of your primary user, and if necessary the secondary user as well. The primary user is most important, and should be considered first in any overlapping use cases.

3. What is important to that audience?
Considering the user profile, what kind of things would be important to them when using your software. For example, if your primary user is elderly, they may require large easily readable fonts and simple structure. If they are 20-something it professionals it should be customizable and accessible via an API.

4. What are the constraints?
This can be anything that constrains the development of the product. It can be anything from browser compatibility to fixed budget. Money is usually the most common and most obvious, but other constraints could be accessibility, timeframe, or competitors.

Questions 2 through 4 combine to form a profile of the criteria you should be using to evaluate every decision that you make in support of your goal.

This is a very basic start, but it should help you to see how product management can help you deliver exceptional software.

Accountability is not a defense

Back in what seems like a lifetime ago, I worked at a great place with some really great people who taught me an important lesson that everyone should be forced to learn. It’s a hard pill to swallow and takes constant work to maintain, but it is a lesson in real accountability and in recognizing your part in every issue you encounter. If I brought a problem or complaint to my boss he would always start by asking me questions. The most important was “what part did you play?”

Accountability is not a defense or an opportunity to blame. What does that mean? It means that accountability is personal responsibility. It is something that you hold yourself to; not something you should outsource to a manager or peer. It’s good to help others recognize opportunities to be more reliable and to expect accountable behavior from people you work with. But it’s the old adage “you can only control the things you can control.” It also means that if someone else fails you can’t use their failure as an excuse for your own.

If you want something to get done right or you have a personal interest in the outcome of something, you should keep an eye on it. Be informed, be a guide and be a facilitator. Make sure the people you count on are put in a position to succeed and follow everything through.

I know that there will be some out there who will argue that you can demand accountability, but in the end, you can’t. You can surround yourself with people who will hold themselves accountable, but you have no control over the behaviors of others. As a manager or a business owner you have the power to force people to follow rules or suffer the consequences, but it’s not the same.

So the next time you think somebody screwed you, think “what did I do that allowed this to happen?” And figure out how you can make sure to not repeat that mistake.

You are complicit in nearly everything that happens to you. There are very few actual victims. The sooner you learn that, and live it, the more you will grow.

UPDATE: Some people asked me who this is for or about. It’s not for anyone, but it is for everyone. Including, and especially, me.

Tagged , ,

Blind faith and dedication are powerful

I just watched this video from NFL.com on Lance Long. Lance was a walk-on at Mississippi State and an undrafted free agent on the practice squad of the Arizona Cardinals. He hopes to be a contributing member of the 53 man roster this year.

His path to professional football has never been easy. But he gets up every day and goes out to make himself better at his job. He strives to be the best he can and contribute to the success of something much bigger than himself. Think about how you approach each of your days. Do you push yourself everyday? Do you strive to be something bigger and better than what people give you credit for? Do you care about something so much that you will blindly follow a path towards it each day without letting the pressure of the future derail you?

I am always moved by stories like these. It illustrates that hard work, focus, and dedication is everything.

Follow

Get every new post delivered to your Inbox.