Tuesday, August 6, 2013

Software Estimating Tips / Tricks / Traps

This post is broken down into the following areas
  1. The presentation given at
       360Stack on Aug 6, 2013
       Houston TechFest on Sept 28, 2013
       Software Craftmanship North American on Nov 9, 2013
       Agile Leadership Network - Houston on Feb 20, 2014
       PMIHouston - June 8, 2015
  2. The highlights from the presentation, in case you don't want to read the slides
  3. Resources
  4. Questions that were asked during the presentation
  5. Backstory to the presentation
  6. Cross-links
  7. Feedback and comments


Software Estimating: Tips for upping your SWAG

I'd love to hear your feedback

9 Tips for improving your software estimating abilities


  1. Determine if you are supposed to be estimating or hitting a target
  2. Use units that are consistent with the estimates underlying accuracy
  3. Explicitly express the uncertainty in your estimates
  4. Collect and use historical data
  5. Count when possible; compute when you can't count
  6. Do a pre-mortem
  7. Envision someone else (not you) doing the work
  8. Remember the most commonly forgotten project related tasks
  9. NEVER TRY. Do or do not. Manage your commitment and your implied commitment with vigilance. 


Resources:


Questions from presentation

  • Could you talk about larger projects, like bigger than six months. Do these techniques still apply?
     The "Demystifying the Black Art" book is absolutely structured to discuss which techniques work at which stage of the project. It also categorizes by project size, what stage in the project, and type of project (iterative or sequential).
  • How do you build in scope creep into your estimate?
    Put that into your explicit range as a +2 months for 20% new features, or if you are unsure about the client have a +6 month or whatever risk quantification. 
  • Do I charge for estimates?
    I wish clients would pay for it because it is a lot of work, but sadly, no I don't. 
  • Estimating based on historical data... isn't that like your stock prospectus "Past performance doesn't guarantee future performance"?
    Not really, the market is driven by so many factors, but this isn't the case, this is YOUR historical data. Unless your team has had a complete overhaul of people, or you have done a Matrix like download of new skills, your team's historical data is an incredible accurate model to base similar projects against. But beware of the intuitive trap, use concrete numbers (size, number of stories, number of screens, etc) to do the comparison. If you are using intuition or memory for the comparison, you will likely not get a good estimate. 
  • How much effort do I put explaining this [the concepts in this presentation] to the client?
    I make sure it comes out in my language. First I clarify if I'm creating an estimate or hitting a target. If I'm creating an estimate, I make sure that I use estimate and commitment in the same time frame.  Something like the estimate is 5 months, but I can commit to you that I'll deliver something of value, that is less than the whole thing, to you in three months. Give me 2 weeks to get into it, and I can give you a good sense of what that might be. 

    The overall trap, is that you want to avoid committing at the big end of the cone, when it is most uncertain and unclear about what the project is about. 
  • Do you give one estimate to the employees, and an later estimate to the client, so that way the employees finish early?
    Personally, this question made me uncomfortable.  My answer is no, I see no reason to withhold information or give misinformation to my team. As an Agilist, my client is involved all the time. I show them something every week. There is no question to anybody, either on the team or the client, the exact status of the project and if we are on target or not. When my team makes a  commitment, we treat that as such. I can ask my team "I have your word that we will complete all of the things that we say by the time that we said".  If your team is not at a place to give their word, to make that commitment, then it is up to you to determine how you would manage your team and client interactions.
  • Tangent : The research and the book "Drive" by Daniel Pink was mentioned (and I highly recommend it)
  • If estimates are non-negotiable, what happens when you get a new piece of information?
    If you get new information that improves the clarity of the project, and moves you farther into the cone, then by all means, re-estimate. Remember you *should* be re-estimating several times before the end of a project. Estimates are not fixed. 


Backstory on this presentation

I had a great time presenting last year at 360Flex, and I wanted to present again. I knew that since the feel of the conference was changing to be less Flex centric, I wanted to make sure to choose a topic that was generic enough.  At the time, I was working on this crazy estimate with 100+ highly detailed requirements. 

While I was doing this estimate, I thought "I really have no basis for what I'm putting down here.... I'd like to know how to make better estimates" 

Also at the time, I was reading several psychology related books, and the overwhelming consistent information coming from these books, that unless you are an expert at a given task (10K applied hours) that your intuition can easily lead you astray. I was certainly not an expert at estimating and I was completely guessing at what the effort was. 

Therefore, I declared that "Estimating" was going to be my topic, and threw my hat into the ring, so to speak. Immediately I started researching the topic, just in case I got picked. 

The field of estimating is WAAAAAAAY overwhelming. PhD disserations, $100K dollar software packages, complex statistical math, and simple tricks were un-navigably abundant  in my initial research. I decided to narrow my talk to the psychology of estimating; simple things that can to to trick your brain to get you to better estimates. 

I was reading "Thinking Fast and Slow" at the time, and it seemed to fit perfectly with this decision. Half of this mighty book was about professional forecasters and how our environment influences our estimates. It seemed like the perfect match for this presentation.

I started out with an outline based on that book, then I was going to fill it in with details from "Demystifying the Black Art". Once I started reading "Demystifying", that was it... the book was perfectly suited to my presentation. The new outline literally flowed out in an half hour sitting.

It was also fortuitous, because as I was talking to people about the cognitive biases associated with estimating, I got frequent warnings about informing people how poorly their brain works. With these warnings, I was pretty sure that presenting about cognitive biases, it would likely be at best, completely ignored, and at worst, a pretty sizable flame war.

So after several practice presentations to my wife, my mom, the most experienced estimator on the Twin Technologies team, and finally all of  the Twin Technologies team, I have the presentation that is presented to you at 360Stack.




One nice discovery that came about this from this presentation is the "How good of an estimator are you" slide, with the 10 questions. When I was in college, my professor gave us these 10 questions as a quiz. He counted the score as part of the grade, which I wasn't pleased with, as I was average for this test, which was 30%. It was comforting to discover  that 30% is average, even if he didn't mention that fact, and even 20 years later.


Cross links to this blog / presentation

Feedback and comments

  • Fantastic volume of content crammed into a 50 minutes session."
  • Very practical advice on how to estimate projects. One of my favorite sessions."
  • best preso ever!"
  • All around really great! Slides, topic, presentation, speed, q&a, all good
  • The content was well thought out! You did the #1 rule in presenting (tell 'em, tell 'em, tell 'em).
  • Getting access to the slides, opening my eyes to the importance of spending extra time on estimates

Thursday, March 14, 2013

Column Spanning with Flex Spark DataGrid - Part 2

I wrote a prior post ( http://squaredi.blogspot.com/2012/07/column-spanning-with-flex-spark.html ) when I was creating a prototype about column spanning.

I'm going to leave most of the details in that post. I have however put the column spanning into production and discovered some missing logic.

We had a service, that computed user's allocation per week for 2 months that took a long time to run, and we wanted to not lock up the UI while it was running. We wanted a lazy loading solution, that "blocked" out the cells that were not available yet.

Here is what that looked like:

Either scripts and active content are not permitted to run or Adobe Flash Player version 11.1.0 or greater is not installed.

Get Adobe Flash Player

You can hit the button at the top to stop the loading effect.

The latest code can be found at:
https://github.com/dshefman/FlexSparkDataGridSpannableColumns


There were a couple of things that I discovered was missing on ColumnSpanningGridItemRenderer:

  1. Setting the new data to a cell needed to reset the expanded cell
  2. I created a function  called getSpanData() that by default returns data, but could be overwritten if there were nested data structures that was the span data
  3. I added bubbling events, so that the grid could respond to spanning and non-spanning changes as well. 

****Performance Warning*****

There is a performance hit with this spanning solution. You can see it when you scroll. The calculations to determine if spanned and then to reparent and reposition the span takes a toll. Especially if there are alot of spans. For us, that was an acceptable solution, especially since we could rationalize that "it was loading", so of course it is busy doing other things :) 

If you can make it faster, please contribute back on Git. 




Monday, February 11, 2013

Flex GridColumn, complex objects, and default sorting

I recently discovered something about the spark GridColumn. You can pass in a complex type for the dataField.

Say for example that your dataProvider is a collection of Users:

public class User
{
    public var name:String;

    public var id:String;

    public var manager:User;

}


You can specify the gridColumn.datafield as "manager.name"
<s:GridColumn dataField="manager.name" />

This is really cool. Can you can see it in the source code down where the datafield property is set. There is an internal dataFieldPath variable.

Here is the problem that I ran into. I had several columns that had these nested values and I wanted to set up each column to have case insensitive sorting, which is not the default. Using a shared sortFunction was difficult, because I also didn't have direct acces to the dataFieldPath (the nested property), and it would have too much work (in my opinion) to build the object within the sort and then grab the string and then lowercase and compare. It was especially too much work, because it would have negated any label functions that were already in place for these columns.

So here is my solution:


package com.workbook.core.view.datagrid
{
    import mx.formatters.IFormatter;

    import spark.collections.SortField;
    import spark.components.gridClasses.GridColumn;
    import spark.components.gridClasses.GridSortField;

    public class CaseInsensitiveComplexDataPathGridColumn extends GridColumn
    {

        public function CaseInsensitiveComplexDataPathGridColumn()
        {
            super()
        }



        override public function get sortField():SortField
        {
            var sf:SortField = super.sortField;
            const isComplexDataField:Boolean = sf is GridSortField;
            var cF:Function = null;
            if (isComplexDataField && sortCompareFunction == null)
            {
                sf.compareFunction = dataFieldPathSortCompareCaseInsensitive;
            }
            return sf;
        }

        protected function dataFieldPathSortCompareCaseInsensitive(obj1:Object,
                                                                 obj2:Object):int
       {
            if (!obj1 && !obj2)
                return 0;

            if (!obj1)
                return 1;

            if (!obj2)
                return -1;

            const obj1String:String = itemToLabel(obj1).toLowerCase();
            const obj2String:String = itemToLabel(obj2).toLowerCase();

            if ( obj1String < obj2String )
                return -1;

            if ( obj1String > obj2String )
                return 1;

            return 0;
        }


    }

}

What this does, is that when you click on the column header, it grabs the sortfield from the gridColumn (that was the easiest public property to get at). Fortunately if the dataField is complex, it builds a GridSortField object instead of a SortField.

I check for the GridSortField and if there is not already a sortCompareFunction, I assign it to my case insensitive sort function.

Then within the sort function, I call itemToLabel, which fortunately does all of the heavy lifting to determine the nested object's label, calling any labelFunctions as needed.

Then I force to lowercase, and done.

To use, I replace my GridColumn in my dataGrid definition, with CaseInsensitiveComplexDataPathGridColumn.

Wednesday, January 2, 2013

Drive - Book Quotes

I'm starting a new trend, that as I read books, I'm going to list out significant or relevant quotes that I'd like to remember.

Drive

by Daniel Pink:

Something cool about this book is that at the end, there is several levels of summary, from a 140 character twitter summary, an elevator and cocktail party summary, as well as a couple of paragraphs on each chapter.

External motivation ( rewards and punishments) == bad

  1. Extinguish intrinsic motivation
  2. Diminish Performance
  3. Crush Creativity
  4. Crowd out good behavior
  5. Encourages cheating, shortcuts, and unethical behavior
  6. Addictive
  7. Fosters short - term thinking

The Three Elements of intrinsic motivations

  • Autonomy

    • Autonomy over the task
    • Autonomy over their time
    • Autonomy over their technique
    • Autonomy over their team
"The most autonomy crushing mechanism imaginable: the billable hour. Most lawyers must track time, often in six minute increments. If they fail to bill enough hours, their jobs are in jeopardy. As a result their focus inevitably veers from output of their work (solving the clients problem) to its input (piling up as many hours as possible). "
The billable hour makes sense for routine tasks, but for non-routine tasks, the link between how much time somebody spends and what that somebody produces is irregular and unpredictable.
The antithesis of the billable hour is the ROWE (Results-only work environment) 

  • Mastery

    • Mastery is a Mindset
      • It is more like strength then height. You can work to improve it. It is in your control
    • Mastery is a Pain
      • "The mundanity of excellence".. spending the most time and effort on the little details that show the tiniest of improvements
    • Mastery is an Asymptote
      • Mastery is impossible to realize fully, because you can always get better. The joy is in the pursuit more than the realization. In the end, mastery attracts precisely because master eludes. 

  • Purpose

    • The yearning to do what we do in the service of something larger than ourselves

Toolkits

Intrinsic Motivations for Parents:


  • Offer praise... the right way
    • Praise effort and strategy, not intelligence
    • Make praise specific
    • Praise in private: Praise is feedback, not an award ceremony.
    • Offer praise only when there is good reason
  • Help kids see the big picture

Thursday, November 15, 2012

Always linking Amazon to the school rewards


Our elementary school has a link off the PTO website, where proceeds from the sale on Amazon will be donated to the school. That's great, but I always forget to click the link first before I go shopping.

I checked with Amazon tech support and the feature to save / manage that within my account is not a current feature (although I requested it).

So now what.

Chrome Extensions: Redirector

This will take a url, like www.amazon.com, and redirect it to the one that has the school links.
Note, that I'm sure there are similar tools for the other browsers, but this one is for Chrome.

Here are the steps that you will need to follow to set this up.
  1. From Chrome, download Redirector 
  2. Click on Rules Manager
  3. Click on the red plus (+) next to the word "Name"
  4. There are four text fields:
Name: (Whatever you want)
Amazon to KolterAmazon


Match
www.amazon.com


Substitution
(www.amazon.com)/?([^\?]*)\??(.*)


Replacement
$1/$2?$3&tag=kolelepto-20&camp=212677&creative=384117&linkCode=ur1&adid=0EN8T40BVQFZ0NCS99MQ&


What this will do is it will find
  • www.amazon.com
  • www.amazon.com/
  • www.amazon.com/anything_else_without_a_question_mark
  • www.amazon.com/anything?anything
and it will append the school information on the end. 
The school information is the part that says:
&tag=kolelepto-20&camp=212677&creative=384117&linkCode=ur1&adid=0EN8T40BVQFZ0NCS99MQ&

And now, whenever you navigate to www.amazon.com, it should automatically think that you clicked on the support the school link. 

Friday, October 26, 2012

On Being a Senior Engineer, Estimating

So, I'm moving from being a freelance consultant to a "technical lead". While I feel that I have a lot of skills in that area already, I'm always looking to grow.

So with that I'm going to be adding some posts about what it means to be a technical lead.

Also, I'm thinking about designing a presentation around estimating, because that is something that I want to learn more about. So I'm also going to be adding some estimation research up here.

And of course, other technical discoveries, AS3, flex, and others will always be here.

So I just came across this blog, On Being a Senior Engineer which I think is fantastic, and here are the bullets:

  •  Mature engineers seek out constructive criticism of their designs.
  • Mature engineers understand the non-technical areas of how they are perceived.
  • Mature engineers do not shy away from making estimates, and are always trying to get better at it.
  • Mature engineers have an innate sense of anticipation, even if they don’t know they do.
  • Mature engineers understand that not all of their projects are filled with rockstar-on-stage work.
  • Mature engineers lift the skills and expertise of those around them.
  • Mature engineers make their trade-offs explicit when making judgements and decisions.
  • Mature engineers don’t practice CYAE (“Cover Your Ass Engineering”)
  • Mature engineers are empathetic.
  • Mature engineers don’t make empty complaints.
  • Mature engineers are aware of cognitive biases


And some of the points about estimation:
Estimation is really about responsibility

(Quoted directly from the blog)

From the Unwritten Laws:
Promises, schedules, and estimates are necessary and important instruments in a well-ordered business. Many engineers fail to realize this, or habitually try to dodge the irksome responsibility for making commitments. You must make promises based upon your own estimates for the part of the job for which you are responsible, together with estimates obtained from contributing departments for their parts. No one should be allowed to avoid the issue by the old formula, “I can’t give a promise because it depends upon so many uncertain factors.”
Avoiding responsibility for estimates is another way of saying, “I’m not ready to be relied upon for building critical pieces of infrastructure.” All businesses rely on estimates, and all engineers working on a project are involved in Joint Activity, which means that they have a responsibility to others to make themselves interpredictable. In general, mature engineers are comfortable with working within some nonzero amount of uncertainty and risk.

And there is a cognitive biases (one of my weaknesses) around estimating

Planning Fallacy – (related to the point about making estimates under uncertainty, above) basically: being more optimistic about forecasting the time a particular project will take.



Thursday, October 25, 2012

Remote Debugging a swf on Android

So I recently had a very thorny challenge of debugging on android.

Because of business / technical reasons, we HAD to serve the swf via HTML through a specific server. The problem that I was having was that the at full screen the video went blank, although we could hear the audio.

Now just as some background, the project was inherited and while there was a decent MVC architecture in place, it was possible that any element on the screen had access to any other element and could modify its properties.... which happened quite a bit.

My challenge was to try to figure out how to get *some* information out of the device so I could have a clue as to what was going on.

I tried to reverse tether and proxy, but neither of those I could do without rooting, which I wasn't willing to do.

Then I tried setting up a hotspot from my laptop (http://www.connectify.me/) to see if I could get Charles in place to then do a local mapping which I could leverage for remote debugging in the IDE, but my version of Android didn't like ad-hoc networks.

Finally I discovered that Monster Debugger had a P2P version. This version allowed me to run demonster on my desktop and the app on the device and as long as they were on the same wifi network, I could get some telemetry. ROCK ON!

So I created a MonsterTraceTarget to go with my logging, and I got trace statements. I could also drill into the visual hierarchy and validate and set properties.

After much searching I found the video element about 16 levels deep with a width and height set to 0,0. This explains the audio but no video. Traces confirmed that somewhere in the code we were hitting the video api (not AS3, but a wrapper to the 3rd party video provider) and actually setting these crazy properties.

"Find Uses" (thank you IntelliJ), led me to half a dozen places where this could happen. More trace statements to determine which one was the culprit. Iterating on the "find uses" and trace statements, I finally discovered that it was an omission that had happened *months* earlier (so much for test early, test often), where there was a conditional test within the configuration startup for touch device and full screen (duh), where the stage rectangle was supposed to be calculated, but wasn't - hence the zeros.

Huge thanks to Demonster and IntelliJ for the tools needed to solve this 2-days-worth-of research thorny issue.