Skip to content

Feed aggregator

Agile Games at Agile Open Southern California

Agile Learning Labs - Sun, 09/14/2014 - 04:55

Our very own Laura Powers recently participated in Agile Open Southern California, where she was interviewed by Scott Dunn. Laura talks about the power of games to help executives understand the changes they need to make in order for their organizations to become more agile.

The video was put together by Cliff Rosa of Rosa Media Productions.

Categories: Companies

iOS Today Widget in Swift - Tutorial

Xebia Blog - Sat, 09/13/2014 - 19:51

Since both the new app extensions of iOS 8 and Swift are both fairly new, I created a sample app that demonstrates how a simple Today extension can be made for iOS 8 in Swift. This widget will show the latest blog posts of the Xebia Blog within the today view of the notification center.

The source code of the app is available on GitHub. The app is not available on the App Store because it's an example app, though it might be quite useful for anyone following this Blog.

In this tutorial, I'll go through the following steps:

New Xcode project

Even though an extension for iOS 8 is a separate binary than an app, it's not possible to create an extension without an app. That makes it unfortunately impossible to create stand alone widgets, which this sample would be since it's only purpose is to show the latest posts in the Today view. So we create a new project in Xcode and implement a very simple view. The only thing the app will do for now is tell the user to swipe down from the top of the screen to add the widget.

iOS Simulator Screen Shot 11 Sep 2014 23.13.21

Time to add our extension target. From the File menu we choose New > Target... and from the Application Extension choose Today Extension.

Screen Shot 2014-09-11 at 23.20.34

We'll name our target XebiaBlogRSSWidget and of course use Swift as Language.

XebiaBlogRSS

The created target will have the following files:

      • TodayViewController.swift
      • MainInterface.storyboard
      • Info.plist

Since we'll be using a storyboard approach, we're fine with this setup. If however we wanted to create the view of the widget programatically we would delete the storyboard and replace the NSExtensionMainStoryboard key in the Info.plist with NSExtensionPrincipalClass and TodayViewController as it's value. Since (at the time of this writing) Xcode cannot find Swift classes as extension principal classes, we also would have to add the following line to our TodayViewController:

@objc (TodayViewController)
Add dependencies with cocoapods

The widget will get the latest blog posts from the RSS feed of the blog: http://blog.xebia.com/feed/. That means we need something that can read and parse this feed. A search on RSS at Cocoapods gives us the BlockRSSParser as first result. Seems to do exactly what we want, so we don't need to look any further and create our Podfile with the following contents:

platform :ios, "8.0"

target "XebiaBlog" do

end

target "XebiaBlogRSSWidget" do
pod 'BlockRSSParser', '~> 2.1'
end

It's important to only add the dependency to the XebiaBlogRSSWidget target since Xcode will build two binaries, one for the app itself and a separate one for the widget. If we would add the dependency to all targets it would be included in both binaries and thus increasing the total download size for our app. Always only add the necessary dependencies to both your app target and widget target(s).

Note: Cocoapods or Xcode might give you problems when you have a target without any Pod dependencies. In that case you may add a dependency to your main target and run pod install, after which you might be able to delete it again.

The BlockRSSParser is written in objective-c, which means we need to add an objective-c bridging header in order to use it from Swift. We add the file XebiaBlogRSSWidget-Bridging-Header.h to our target and add the import.

#import "RSSParser.h"

We also have to tell the Swift compiler about it in our build settings:

Screen Shot 2014-09-12 at 15.35.21

Load RSS feed

Finally time to do some coding. The generated TodayViewController has a function called widgetPerformUpdateWithCompletionHandler. This function gets called every once in awhile to ask for new data. It also gets called right after viewDidLoad when the widget is displayed. The function has a completion handler as parameter, which we need to call when we're done loading data. A completion handler is used instead of a return function so we can load our feed asynchronously.

In objective-c we would write the following code to load our feed:

[RSSParser parseRSSFeedForRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://blog.xebia.com/feed/"]] success:^(NSArray *feedItems) {
  // success
} failure:^(NSError *error) {
  // failure
}];

In Swift this looks slightly different. Here the the complete implementation of widgetPerformUpdateWithCompletionHandler:

func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
  let url = NSURL(string: "http://blog.xebia.com/feed/")
  let req = NSURLRequest(URL: url)

  RSSParser.parseRSSFeedForRequest(req,
    success: { feedItems in
      self.items = feedItems as? [RSSItem]
      completionHandler(.NewData)
    },
    failure: { error in
      println(error)
      completionHandler(.Failed)
  })
}

We assign the result to a new optional variable of type RSSItem array:

var items : [RSSItem]?

The completion handler gets called with either NCUpdateResult.NewData if the call was successful or NCUpdateResult.Failed when the call failed. A third option is NCUpdateResult.NoData which is used to indicate that there is no new data. We'll get to that later in this post when we cache our data.

Show items in a table view

Now that we have fetched our items from the RSS feed, we can display them in a table view. We replace our normal View Controller with a Table View Controller in our Storyboard and change the superclass of TodayViewController and add three labels to the prototype cell. No different than in iOS 7 so I won't go into too much detail here (the complete project is on GitHub).

We also create a new Swift class for our custom Table View Cell subclass and create outlets for our 3 labels.

import UIKit

class RSSItemTableViewCell: UITableViewCell {

    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var authorLabel: UILabel!
    @IBOutlet weak var dateLabel: UILabel!

}

Now we can implement our Table View Data Source functions.

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  if let items = items {
    return items.count
  }
  return 0
}

Since items is an optional, we use Optional Binding to check that it's not nil and then assign it to a temporary non optional variable: let items. It's fine to give the temporary variable the same name as the class variable.

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCellWithIdentifier("RSSItem", forIndexPath: indexPath) as RSSItemTableViewCell

  if let item = items?[indexPath.row] {
    cell.titleLabel.text = item.title
    cell.authorLabel.text = item.author
    cell.dateLabel.text = dateFormatter.stringFromDate(item.pubDate)
  }

  return cell
}

In our storyboard we've set the type of the prototype cell to our custom class RSSItemTableViewCell and used RSSItem as identifier so here we can dequeue a cell as a RSSItemTableViewCell without being afraid it would be nil. We then use Optional Binding to get the item at our row index. We could also use forced unwrapping since we know for sure that items is not nil here:

let item = items![indexPath.row]

But the optional binding makes our code saver and prevents any future crash in case our code would change.

We also need to create the date formatter that we use above to format the publication dates in the cells:

let dateFormatter : NSDateFormatter = {
        let formatter = NSDateFormatter()
        formatter.dateStyle = .ShortStyle
        return formatter
    }()

Here we use a closure to create the date formatter and to initialise it with our preferred date style. The return value of the closure will then be assigned to the property.

Preferred content size

To make sure we that we can actually see the table view we need to set the preferred content size of the widget. We'll add a new function to our class that does this.

func updatePreferredContentSize() {
  preferredContentSize = CGSizeMake(CGFloat(0), CGFloat(tableView(tableView, numberOfRowsInSection: 0)) * CGFloat(tableView.rowHeight) + tableView.sectionFooterHeight)
}

Since the widgets all have a fixed width, we can simply specify 0 for the width. The height is calculated by multiplying the number of rows with the height of the rows. Since this will set the preferred height greater than the maximum allowed height of a Today widget it will automatically shrink. We also add the sectionFooterHeight to our calculation, which is 0 for now but we'll add a footer later on.

When the preferred content size of a widget changes it will animate the resizing of the widget. To have the table view nicely animating along this transition, we add the following function to our class which gets called automatically:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
  coordinator.animateAlongsideTransition({ context in
    self.tableView.frame = CGRectMake(0, 0, size.width, size.height)
  }, completion: nil)
}

Here we simply set the size of the table view to the size of the widget, which is the first parameter.

Of course we still need to call our update method as well as reloadData on our tableView. So we add these two calls to our success closure when we load the items from the feed

success: { feedItems in
  self.items = feedItems as? [RSSItem]
  
  self.tableView.reloadData()
  self.updatePreferredContentSize()

  completionHandler(.NewData)
},

Let's run our widget:

Screen Shot 2014-09-09 at 13.12.50

It works, but we can make it look better. Table views by default have a white background color and black text color and that's no different within a Today widget. We'd like to match the style with the standard iOS Today widget so we give the table view a clear background and make the text of the labels white. Unfortunately that does make our labels practically invisible since the storyboard editor in Xcode will still show a white background for views that have a clear background color.

If we run again, we get a much better looking result:

Screen Shot 2014-09-09 at 13.20.05

Open post in Safari

To open a Blog post in Safari when tapping on an item we need to implement the tableView:didSelectRowAtIndexPath: function. In a normal app we would then use the openURL: method of UIApplication. But that's not available within a Today extension. Instead we need to use the openURL:completionHandler: method of NSExtensionContext. We can retrieve this context through the extensionContext property of our View Controller.

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
  if let item = items?[indexPath.row] {
    if let context = extensionContext {
      context.openURL(item.link, completionHandler: nil)
    }
  }
}
More and Less buttons

Right now our widget takes up a bit too much space within the notification center. So let's change this by showing only 3 items by default and 6 items maximum. Toggling between the default and expanded state can be done with a button that we'll add to the footer of the table view. When the user closes and opens the notification center, we want to show it in the same state as it was before so we need to remember the expand state. We can use the NSUserDefaults for this. Using a computed property to read and write from the user defaults is a nice way to write this:

let userDefaults = NSUserDefaults.standardUserDefaults()

var expanded : Bool {
  get {
    return userDefaults.boolForKey("expanded")
  }
  set (newExpanded) {
    userDefaults.setBool(newExpanded, forKey: "expanded")
    userDefaults.synchronize()
  }
}

This allows us to use it just like any other property without noticing it gets stored in the user defaults. We'll also add variables for our button and number of default and maximum rows:

let expandButton = UIButton()

let defaultNumRows = 3
let maxNumberOfRows = 6

Based on the current value of the expanded property we'll determine the number of rows that our table view should have. Of course it should never display more than the actual items we have so we also take that into account and change our function into the following:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  if let items = items {
    return min(items.count, expanded ? maxNumberOfRows : defaultNumRows)
  }
  return 0
}

Then the code to make our button work:

override func viewDidLoad() {
  super.viewDidLoad()

  updateExpandButtonTitle()
  expandButton.addTarget(self, action: "toggleExpand", forControlEvents: .TouchUpInside)
  tableView.sectionFooterHeight = 44
}

override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
  return expandButton
}

Depending on the current value of our expanded property we wil show either "Show less" or "Show more" as button title.

func updateExpandButtonTitle() {
  expandButton.setTitle(expanded ? "Show less" : "Show more", forState: .Normal)
}

When we tap the button, we'll invert the expanded property, update the button title and preferred content size and reload the table view data.

func toggleExpand() {
  expanded = !expanded
  updateExpandButtonTitle()
  updatePreferredContentSize()
  tableView.reloadData()
}

And as a result we can now toggle the number of rows we want to see.

Screen Shot 2014-09-13 at 18.53.39Screen Shot 2014-09-13 at 18.53.43

Caching

At this moment, each time we open the widget, we first get an empty list and then once the feed is loaded, the items are displayed. To improve this, we can cache the retrieved items and display those once the widget is opened before we load the items from the feed. The TMCache library makes this possible with little effort. We can add it to our Pods file and bridging header the same way we did for the BlockRSSParser library.

Also here, a computed property works nice for caching the items and hide the actual implementation:

var cachedItems : [RSSItem]? {
  get {
    return TMCache.sharedCache().objectForKey("feed") as? [RSSItem]
  }
  set (newItems) {
    TMCache.sharedCache().setObject(newItems, forKey: "feed")
  }
}

Since the RSSItem class of the BlockRSSParser library conforms to the NSCoding protocol, we can use them directly with TMCache. When we retrieve the items from the cache for the first time, we'll get nil since the cache is empty. Therefore cachedItems needs to be an optional as well as the downcast and therefore we need to use the as? operator.

We can now update the cache once the items are loaded simply by assigning a value to the property. So in our success closure we add the following:

self.cachedItems = self.items

And then to load the cached items, we add two more lines to the end of viewDidLoad:

items = cachedItems
updatePreferredContentSize()

And we're done. Now each time the widget is opened it will first display the cached items.

There is one last thing we can do to improve our widget. As mentioned earlier, the completionHandler of widgetPerformUpdateWithCompletionHandler can also be called with NCUpdateResult.NoData. Now that we have the items that we loaded previously we can compare newly loaded items with the old and use NoData in case they haven't changed. Here is our final implementation of the success closure:

success: { feedItems in
  if self.items == nil || self.items! != feedItems {
    self.items = feedItems as? [RSSItem]
    self.tableView.reloadData()
    self.updatePreferredContentSize()
    self.cachedItems = self.items
    completionHandler(.NewData)
  } else {
    completionHandler(.NoData)
  }
},

And since it's Swift, we can simply use the != operator to see if the arrays have unequal content.

Source code on GitHub

As mentioned in the beginning of this post, the source code of the project is available on GitHub with some minor changes that are not essential to this blog post. Of course pull requests are always welcome. Also let me know in the comments below if you'd wish to see this widget released on the App Store.

Categories: Companies

R: ggplot – Plotting a single variable line chart (geom_line requires the following missing aesthetics: y)

Mark Needham - Sat, 09/13/2014 - 13:41

I’ve been learning how to do moving averages in R and having done that calculation I wanted to plot these variables on a line chart using ggplot.

The vector of rolling averages looked like this:

> rollmean(byWeek$n, 4)
  [1]  3.75  2.00  1.25  1.00  1.25  1.25  1.75  1.75  1.75  2.50  2.25  2.75  3.50  2.75  2.75
 [16]  2.25  1.50  1.50  2.00  2.00  2.00  2.00  1.25  1.50  2.25  2.50  3.00  3.25  2.75  4.00
 [31]  4.25  5.25  7.50  6.50  5.75  5.00  3.50  4.00  5.75  6.25  6.25  6.00  5.25  6.25  7.25
 [46]  7.75  7.00  4.75  2.75  1.75  2.00  4.00  5.25  5.50 11.50 11.50 12.75 14.50 12.50 11.75
 [61] 11.00  9.25  5.25  4.50  3.25  4.75  7.50  8.50  9.25 10.50  9.75 15.25 16.00 15.25 15.00
 [76] 10.00  8.50  6.50  4.25  3.00  4.25  4.75  7.50 11.25 11.00 11.50 10.00  6.75 11.25 12.50
 [91] 12.00 11.50  6.50  8.75  8.50  8.25  9.50  8.50  8.75  9.50  8.00  4.25  4.50  7.50  9.00
[106] 12.00 19.00 19.00 22.25 23.50 22.25 21.75 19.50 20.75 22.75 22.75 24.25 28.00 23.00 26.00
[121] 24.25 21.50 26.00 24.00 28.25 25.50 24.25 31.50 31.50 35.75 35.75 29.00 28.50 27.25 25.50
[136] 27.50 26.00 23.75

I initially tried to plot a line chart like this:

library(ggplot2)
library(zoo)
rollingMean = rollmean(byWeek$n, 4)
qplot(rollingMean) + geom_line()

which resulted in this error:

stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.
Error: geom_line requires the following missing aesthetics: y

It turns out we need to provide an x and y value if we want to draw a line chart. In this case we’ll generate the ‘x’ value – we only care that the y values get plotted in order from left to right:

qplot(1:length(rollingMean), rollingMean, xlab ="Week Number") + geom_line()
2014 09 13 16 58 57

If we want to use the ‘ggplot’ function then we need to put everything into a data frame first and then plot it:

ggplot(data.frame(week = 1:length(rollingMean), rolling = rollingMean),
       aes(x = week, y = rolling)) +
  geom_line()

2014 09 13 17 11 13

Categories: Blogs

R: Calculating rolling or moving averages

Mark Needham - Sat, 09/13/2014 - 10:15

I’ve been playing around with some time series data in R and since there’s a bit of variation between consecutive points I wanted to smooth the data out by calculating the moving average.

I struggled to find an in built function to do this but came across Didier Ruedin’s blog post which described the following function to do the job:

mav <- function(x,n=5){filter(x,rep(1/n,n), sides=2)}

I tried plugging in some numbers to understand how it works:

> mav(c(4,5,4,6), 3)
Time Series:
Start = 1 
End = 4 
Frequency = 1 
[1]       NA 4.333333 5.000000       NA

Here I was trying to do a rolling average which took into account the last 3 numbers so I expected to get just two numbers back – 4.333333 and 5 – and if there were going to be NA values I thought they’d be at the beginning of the sequence.

In fact it turns out this is what the ‘sides’ parameter controls:

sides	
for convolution filters only. If sides = 1 the filter coefficients are for past values only; if sides = 2 they 
are centred around lag 0. In this case the length of the filter should be odd, but if it is even, more of the 
filter is forward in time than backward.

So in our ‘mav’ function the rolling average looks both sides of the current value rather than just at past values. We can tweak that to get the behaviour we want:

mav <- function(x,n=5){filter(x,rep(1/n,n), sides=1)}
> mav(c(4,5,4,6), 3)
Time Series:
Start = 1 
End = 4 
Frequency = 1 
[1]       NA       NA 4.333333 5.000000

The NA values are annoying for any plotting we want to do so let’s get rid of them:

> na.omit(mav(c(4,5,4,6), 3))
Time Series:
Start = 3 
End = 4 
Frequency = 1 
[1] 4.333333 5.000000

Having got to this point I noticed that Didier had referenced the zoo package in the comments and it has a built in function to take care of all this:

> library(zoo)
> rollmean(c(4,5,4,6), 3)
[1] 4.333333 5.000000

I also realised I can list all the functions in a package with the ‘ls’ function so I’ll be scanning zoo’s list of functions next time I need to do something time series related – there’ll probably already be a function for it!

> ls("package:zoo")
  [1] "as.Date"              "as.Date.numeric"      "as.Date.ts"          
  [4] "as.Date.yearmon"      "as.Date.yearqtr"      "as.yearmon"          
  [7] "as.yearmon.default"   "as.yearqtr"           "as.yearqtr.default"  
 [10] "as.zoo"               "as.zoo.default"       "as.zooreg"           
 [13] "as.zooreg.default"    "autoplot.zoo"         "cbind.zoo"           
 [16] "coredata"             "coredata.default"     "coredata<-"          
 [19] "facet_free"           "format.yearqtr"       "fortify.zoo"         
 [22] "frequency<-"          "ifelse.zoo"           "index"               
 [25] "index<-"              "index2char"           "is.regular"          
 [28] "is.zoo"               "make.par.list"        "MATCH"               
 [31] "MATCH.default"        "MATCH.times"          "median.zoo"          
 [34] "merge.zoo"            "na.aggregate"         "na.aggregate.default"
 [37] "na.approx"            "na.approx.default"    "na.fill"             
 [40] "na.fill.default"      "na.locf"              "na.locf.default"     
 [43] "na.spline"            "na.spline.default"    "na.StructTS"         
 [46] "na.trim"              "na.trim.default"      "na.trim.ts"          
 [49] "ORDER"                "ORDER.default"        "panel.lines.its"     
 [52] "panel.lines.tis"      "panel.lines.ts"       "panel.lines.zoo"     
 [55] "panel.plot.custom"    "panel.plot.default"   "panel.points.its"    
 [58] "panel.points.tis"     "panel.points.ts"      "panel.points.zoo"    
 [61] "panel.polygon.its"    "panel.polygon.tis"    "panel.polygon.ts"    
 [64] "panel.polygon.zoo"    "panel.rect.its"       "panel.rect.tis"      
 [67] "panel.rect.ts"        "panel.rect.zoo"       "panel.segments.its"  
 [70] "panel.segments.tis"   "panel.segments.ts"    "panel.segments.zoo"  
 [73] "panel.text.its"       "panel.text.tis"       "panel.text.ts"       
 [76] "panel.text.zoo"       "plot.zoo"             "quantile.zoo"        
 [79] "rbind.zoo"            "read.zoo"             "rev.zoo"             
 [82] "rollapply"            "rollapplyr"           "rollmax"             
 [85] "rollmax.default"      "rollmaxr"             "rollmean"            
 [88] "rollmean.default"     "rollmeanr"            "rollmedian"          
 [91] "rollmedian.default"   "rollmedianr"          "rollsum"             
 [94] "rollsum.default"      "rollsumr"             "scale_x_yearmon"     
 [97] "scale_x_yearqtr"      "scale_y_yearmon"      "scale_y_yearqtr"     
[100] "Sys.yearmon"          "Sys.yearqtr"          "time<-"              
[103] "write.zoo"            "xblocks"              "xblocks.default"     
[106] "xtfrm.zoo"            "yearmon"              "yearmon_trans"       
[109] "yearqtr"              "yearqtr_trans"        "zoo"                 
[112] "zooreg"
Categories: Blogs

Poaching vs. Collaboration

Agile Tools - Sat, 09/13/2014 - 08:13

adventure-evening-fun-2029-825x550

No one wants advice, only collaboration. – John Steinbeck

Imagine you are working as part of a team on a project. One day your manager approaches you and says, “There is this really high priority project that has come up and we need you and your expertise on it. We are going to move you onto that team for the duration of the project. Is that OK with you?”

How would you feel about that? I know how I would feel. I would feel jerked around. I would not feel in control or part of the decision making. I might even feel that the value of my membership to the team that I’m already on is being discounted. In short, it would suck.

How do you think your team would feel about it? Would they feel like they were able to participate in, let alone determine, the membership of their team? They wouldn’t feel in control of anything either. In fact, they might even feel victimized by the whole experience. They might be thinking, “Geez, we are screwed. How are we going to finish this project without Joe?” They might even wonder why you were the one who was chosen. That could lead to all sorts of fun misunderstandings.

So what would you do instead? After all, there is this project or team that needs help. It’s a top priority – a higher priority than anything else you are working on now. How can we manage this situation without destroying the integrity of the team?

Instead of moving individuals we could take the problem to the whole team. Perhaps a manager would come and sit down with the team and describe what they need. They could explain the trade offs and the specifics of what the other team needs help with. Then they might ask, “Could you guys help this other team out…as a team.”

This would have all sorts of advantages. If a team needs help and you send them just one guy, you’ve increased your team size by one person. If instead, an entire team pitches in to help, then you get the resources of 6 or 7 guys. Forget whatever multiplier effect you might get from a closely knit team – which solution is going to deliver results faster? That’s right, the team of 7. And there is more benefit besides productivity. By engaging the team in this fashion you are asking them to remain a team, and to help another team. Team’s helping teams – what a great idea!

You don’t hurt morale. You leave the decisions on how to manage the problem to the teams – so they feel like they own the problem. They are engaged, they are helping someone else. It really does have a lot going for it.

So what about that other project you were working on? You know, the one that you had to put down to help out with that other team? What about that project? Wasn’t it important too? Sure, but it wasn’t as high a priority, so it waits. This encourages the kind of organizational focus where everyone is attending to the most important issues first, rather than scattering their efforts across multiple lower priority issues in the name of higher utilization or productivity.

So if you are currently in the habit of pulling people off of teams in order to solve resourcing problems, I’m here to tell you that there is another way. If you are open minded enough to give it a try, you might just find that it may be a better way.


Filed under: Agile, Teams Tagged: Collaboration, control, micro management, poaching, resource management, Teams
Categories: Blogs

React In Modern Web Applications: Part 2

Xebia Blog - Fri, 09/12/2014 - 23:32

As mentioned in part 1 of this series, React is an excellent Javascript library for writing highly dynamic client-side components. However, React is not meant to be a complete MVC framework. Its strength is the View part of the Model-View-Controller pattern. AngularJS is one of the best known and most powerful Javascript MVC frameworks. One of the goals of the course was to show how to integrate React with AngularJS.

Integrating React with AngularJS

Developers can create reusable components in AngularJS by using directives. Directives are very powerful but complex, and the code quickly tends to becomes messy and hard to maintain. Therefore, replacing the directive content in your AngularJS application with React components is an excellent use-case for React. In the course, we created a Timesheet component in React. To use it with AngularJS, create a directive that loads the WeekEntryComponent:

angular.module('timesheet')
    .directive('weekEntry', function () {
        return {
            restrict: 'A',
            link: function (scope, element) {
                React.renderComponent(new WeekEntryComponent({
                                             scope.companies, 
                                             scope.model}), element.find('#weekEntry')[0]);
            }
        };
    });

as you can see, a simple bit of code. Since this is AngularJS code, I prefer not to use JSX, and write the React specific code in plain Javascript. However, if you prefer you could use JSX syntax (do not forget to add the directive at the top of the file!). We are basically creating a component and rendering it on the element with id weekentry. We pass two values from the directive scope to the WeekEntryComponent as properties. The component will render based on the values passed in.

Reacting to changes in AngularJS

However, the code as shown above has one fatal flaw: the component will not re-render when the companies or model values change in the scope of the directive. The reason is simple: React does not know these values are dynamic, and the component gets rendered once when the directive is initialised. React re-renders a component in only two situations:

  • If the value of a property changes: this allows parent components to force re-rendering of child components
  • If the state object of a component changes: a component can create a state object and modify it

State should be kept to a minimum, and preferably be located in only one component. Most components should be stateless. This makes for simpler, easier to maintain code.

To make the interaction between AngularJS and React dynamic, the WeekEntryComponent must be re-rendered explicitly by AngularJS whenever a value changes in the scope. AngularJS provides the watch function for this:

angular.module('timesheet')
  .directive('weekEntry', function () {
    return {
      restrict: 'A',
      link: function (scope, element) {
        scope.$watchCollection('[clients, model]', function (newData) {
          if (newData[0] !== undefined && newData[1] !== undefined) {
            React.renderComponent(new WeekEntryComponent({
                rows: newData[1].companies,
                clients: newData[0]
              }
            ), element.find('#weekEntry')[0]);
          }
        });
      }
    };
  });

In this code, AngularJS watches two values in the scope, clients and model, and when one of the values is changed by an user action the function gets called, re-rendering the React component only when both values are defined. If most of the scope is needed from AngularJS, it is better to pass in the complete scope as property, and put a watch on the scope itself. Remember, React is very smart about re-rendering to the browser. Only if a change in the scope properties leads to a real change in the DOM will the browser be updated!

Accessing AngularJS code from React

When your component needs to use functionality defined in AngularJS you need to use a function callback. For example, in our code, saving the timesheet is handled by AngularJS, while the save button is managed by React. We solved this by creating a saveTimesheet function, and adding it to the scope of directive. In the WeekEntryComponent we added a new property: saveMethod:

angular.module('timesheet')
  .directive('weekEntry', function () {
    return {
      restrict: 'A',
      link: function (scope, element) {
        scope.$watchCollection('[clients, model]', function (newData) {
          if (newData[0] !== undefined && newData[1] !== undefined) {
            React.renderComponent(WeekEntryComponent({
              rows: newData[1].companies,
              clients: newData[0],
              saveMethod: scope.saveTimesheet
            }), element.find('#weekEntry')[0]);
          }
        });
      }
    };
  });

Since this function is not going to be changed it does not need to be watched. Whenever the save button in the TimeSheetComponent is clicked, the saveTimesheet function is called and the new state of the timesheet saved.

What's next

In the next part we will look at how to deal with state in your components and how to avoid passing callbacks through your entire component hierarchy when changing state

Categories: Companies

Looking Back at the Past Two Years

Agile For All - Bob Hartman - Fri, 09/12/2014 - 23:30

Eric Engelmann of GeonetricI want to start this post by thanking Eric Englemann (yes, that is him on the right!), the CEO of one of our awesome clients, Geonetric. Almost two years ago he took a huge risk and completely changed their corporate structure. But he didn’t stop there, he committed to letting the world know how they were doing along the way. He and others in his company have been extremely open about their results, including how they were doing one year after the big change and again last month.

Well, two years ago Agile For All underwent a big change as well. It went from a single-member LLC where I was the founder, owner, only member and everything else. In other words I was on my own. Two years ago I merged Agile For All with Richard Lawrence’s company, Humanizing Work. We had worked together for several years prior to the merger, but actually merging our companies was a huge, risky step for both of us. How are we doing today?

In looking back over the past two years I think there are 3 main places where we may have made some mistakes, and 5 main places where we have had huge success. Let’s start with the bad, because they aren’t all that bad!

What we would do differently if we could?
  1. Meet more regularly to challenge our ideas and thoughts. As we learned more and more about each other we realized we not only complemented each other in many ways, but we also have the ability to effectively challenge each other’s thinking. Richard is obviously extremely knowledgeable about agility and other topics. Prior to our merger I often had ideas and had to analyze them by myself. Richard is able to easily poke holes in my ideas, and just as importantly, he is able to expand upon my thinking. Often we end up far away from where we started, but it is an awesome place! We didn’t know each other well enough to do this early on, but I wish it had been possible.
  2. Better integrate our content. For better or worse, Richard and I have different styles of workshop facilitation. Because of this it has been, and still is, difficult to integrate our content. As a result we teach to the same basic learning objectives, but in different ways. Interestingly though, we both have integrated something from the other person in our workshops. We both try to use Training From the Back of the Room (thanks Sharon Bowman!) techniques in our courses, so it isn’t a big stretch at times.
  3. Hire Angie sooner! Having a Marketing and Events Manager has taken so much off of our plates that we are able to keep our sanity. Plus, as any of you who have been to one of our workshops knows, she is just flat out awesome at what she does. I can’t even remember the last time something slipped through the cracks and caused an issue. But there are multiple times when she absolutely saved our butts because something horrible happened. How amazing Angie is has become a joke among our partners and ourselves. Earlier this year a partner said “Wow, this thing is amazing. Of course it is, Angie did it. Good job Angie!” So now we all say the same thing a lot, “This is amazing. Of course it is. Good job Angie!” Maybe we need to have that turned into some sort of emoticon just to save time in email? <grin>
What are the big wins we’ve had?
  1. Hiring Angie. Did I mention we should have done that sooner??? Not having to worry about logistics for our workshops has been a big load off of both Richard and myself. Things are there when we arrive, the rooms are properly set up and everyone has been informed about what to do and expect. It is awesome. But that’s not all Angie does. She does everything from answering the company phone line to completely planning our annual conference (more on that later).
  2. Pair-selling. Having two of us involved in the sales process has helped us better meet the needs of our clients. Richard and I have different experiences which allow us to relate to clients in different ways. We complement each other well when on sales calls and as a result we are better able to service clients.
  3. Having a great life/work balance. We are actually able to prioritize LIFE over work. Running a business yourself is hard work. It takes a lot of time and sucks up every minute if you let it. By merging, we have cut the overhead of running our businesses in half (just one business now instead of two). This has freed up both of us to enjoy life to the fullest. Richard takes time with his family to do downhill mountain biking (yes, he and his family are crazy!), while I have taken time to travel and enjoy golf in Hawaii and Scotland as well as other wonderful places.
  4. Working together at some awesome clients. While we can’t publish our client list, let’s just say there are others that are as much fun as Geonetric. OK, maybe not that much fun, but lots of fun for sure. Prior to our merger we worked together, but we still were competitors so we didn’t work at clients together, mostly we just referred business to each other. Now we actually get to work together at some of our clients and it is always an amazing experience.
  5. The Humanizing Work conference. This is clearly the biggest win we’ve had. When we merged our two companies we discussed what to do with the Humanizing Work name and website. We had a vague idea that we would keep it because it sounded like something we would use in the future. After all, our goal in our workshops is to help people understand how to create software in a way that recognizes the value of people. Last year we decided to host  conference specifically for people who had been to our workshops. While we call it a conference, our goal was to eliminate all the things we disliked about typical conferences. We had an awesome time and so did our conference attendees. If you have been to one of our workshops, you really need to attend this conference. You will never look at conferences the same way again!

In summary, I want to thank Eric for being an example of transparency, but more importantly, I want to thank Richard for being a great business partner and friend. The past two years have been awesome and I’m looking forward to seeing what happens in the future!

AngieOh, and this is Angie. If you see her at our conference or anywhere else, be sure to say “Hi, oh and good job, Angie!”

The post Looking Back at the Past Two Years appeared first on Agile For All.

Categories: Blogs

A Shorty Story on Launching an Agile Release Train

Agile Product Owner - Fri, 09/12/2014 - 19:24

In this short story, Alex Yakyma describes the launching of a (mostly) fictional Agile Release Train as part of an initial SAFe adoption and, most importantly, the courageous people that drive change and some of the interesting situations they face. You can download it here:

Pacific Express: A Short Story

It’s a fun, light read, and maybe points the way to new mechanisms for describing SAFe adoption “from the inside out.” The nice thing about this format is the ability to see and feel the people and cultural aspects of SAFe, because as a framework, it is just that, and it’s the people that do ALL the work.

Categories: Blogs

I crashed the web servers of a $100M+ multi-national corporation …

Derick Bailey - new ThoughtStream - Fri, 09/12/2014 - 14:00

error

2 Hours.

That’s how long it took me to fix the problem I caused, after crashing the production web servers for a $100M+ multi-national corporation.

And this wasn’t just a marketing site, mind you. This was *the* web presence, online catalog, parts information and primary means of contact for distributors and representatives for several of the largest and most well known brands in that company’s industry. And I crashed every last website the company had, for every brand, for 2 hours.

The Setup

It’s the year 2002. Microsoft had released their brand new .NET framework, Visual Studio and Visual Basic.NET systems. I dove in head first, setting aside my “classic” ASP (VBScript) and VB6/COM components. In a few short months, I had my first ASP.NET / VB.NET application ready to roll. It was the e-catalog for the company’s distributor and representative network. It replaced a manual upload and link process with a completely automated system that allowed product managers to log in and update the categories, products and PDF files on their own.

Less Than 30 minutes after deploying the application to the production servers, the entire suite of web sites that were hosted on those boxes were down and I was getting panicked calls from product managers and customer service reps. My boss was also getting calls from division and brand presidents / CEOs. It wasn’t a good day for me.

Those Pesky “return” Statements

I was panicked. Full on, heart attack, stomach dropping panic.

I turned to the internet to research the problem and help me solve my problem. Why were my database connections being eaten up? Why weren’t they closing, or recycling in the connection pool the way they were supposed to? I have my database connection “.close()” method right there, just like I always did in my classic ASP pages… right there, after my return statements, where I send the data back out to the page from the data access code.

Yeah, you can probably guess from that last line, that this is what my code looked like:

Return SomeData;
MyDatabaseConn.Close();

Oh, the horror when after nearly an hour and a half of searching, I found out that the “return” statement in VB.NET immediately exits the function where it is. How stupid is that? VB6 didn’t do it that way. VBScript (at the time) didn’t do it that way. Why would they change that in VB.NET?! I was horrified! But I was also under the gun to fix it, so I found every database connection “.close()” call and moved them one line above the return statement.

I deployed. It worked. The sites came back up and I slowly started to breathe.

And then my boss called me in to his office…

The Conversation

I sat down and looked at my boss, door closed behind us. I was ready to get fired.

He sat there and looked at me for a moment before asking if the sites were back up. Then he told me how many angry phone calls the customer service reps had received, how many bids we had lost because our reps and distributors couldn’t get the information they needed, and he gave an estimate of the money that we lost in the down time. it was more money than I would make in the next 2 months of work.

Then he asked me what I did wrong and what I learned from the problems and solutions. He wanted to know if I was going to make that mistake again and how I could avoid similar problems in the future.

Lastly – and quite shockingly to me – he told me how the CEO of the company was known to make mistakes of that caliber … every day… and that, while I had caused a lot of damage for a short period of time, it would be washed out by the end of the month.

Lesson Learned

The important lesson, he told me, was that I owned up to the mistake, dug in and fixed it, and learned how to avoid the problem in the future. I was, in his mind, a better developer at the end of that day. I had survived a catastrophic crash of my own making and I had fixed the problem, learning some very valuable lessons in business down time and in code that day.

Fail Your Way To Success

I’ll never forget that lesson. I was 23 years old, running the public web sites for multiple brands inside of a $100M+ manufacturing company. And my boss taught that that it’s ok to make mistakes – even big ones – as long as we can recover from them and learn from them

He taught me that we don’t need to be afraid of making mistakes. Rather, we need to be afraid of not learning from them.

 

– Derick

      
Categories: Blogs

Scrum Sense News 09/14 – Adventures in Europe

ScrumSense.com - Peter Hundermark - Fri, 09/12/2014 - 13:38

Welcome to our September newsletter and welcome to summer.

Franschhoek_text_LG_SCRT

 

This is the first Scrum Coaching Retreat in Africa. It is an opportunity for you to collaborate with other coaches, learning from each other and producing valuable outcomes that will have lasting benefit to our community and customers.

The theme of this retreat is “small improvements”, recognising that most big changes are better embarked on, digested and internalised one step at a time. Transforming the world of work is a big endeavour. We can contribute by meeting our customers where they are and helping them take one next step.

For first-time visitors to South Africa we promise you an awesome experience in the winelands surrounding our Mother City. Come early or linger an extra week to experience this special place in high summer. For local coaches we promise you deep interactions with some of the best Scrum coaches on the planet.

More information and registration. Twitter hashtag #scrcpt.

Joanne’s Adventures in Europe

CSM in Denmark with Bent MyllerupShortly after joining Scrum Sense in February this year I started my journey to become a Certified Scrum Trainer (CST). The process includes co-training with other CSTs around the world, so that I can get feedback to improve and, once I am good enough, I can get their recommendations that are essential to acceptance. For the past week I have been lucky enough to travel around Europe and co-train with some of the top CSTs and CSCs (Certified Scrum Coaches) in Europe. It has been a wonderful experience for me….more.

 

 

 

Kanban Training

ddab0739-d764-4739-b47d-b43c56234160The popular Applying Kanban (Foundation) course sold out in record time, and all seats have now been filled. We plan to run another course in May 2015, which we have already started taking bookings for. Reserve your place at the May 2015 Applying Kanban (Foundation) course Kanban foundational course provides insight and visibility to the “why” of doing things – Dean Harvey, Nedbank Ltd. We still have a few spaces available for our Improving & Scaling Kanban(Advanced) certified courses which will be taking place in Sandton on the 23-24 Oct 2014. We are running a 3-for-2 special offer, so be sure to secure your place!

 

 

Other News Lean Agile 2014 SA

Peter Hundermark will be presenting at LeanAgile SA 2014 (#LASA) in October.

Scrum Gathering South Africa  20-21 October

Scrum Sense will be at the Scrum Gathering in full force. Catch us presenting on the following subjects:

We hope to see you there. Last years gathering was awesome and packed with amazing speakers from all around the world.

The post Scrum Sense News 09/14 – Adventures in Europe appeared first on ScrumSense.

Categories: Blogs

Pair & Share - a simple technique for Sprint Planning

Scrum Breakfast - Fri, 09/12/2014 - 09:00
How do you get the team to plan tasks effectively?The second half of sprint planning is often a challenge for teams starting Scrum. It used to be their Project Leader would do the planning for them. Now the team has to figure it out for themselves! (Doesn't the Scrum Master do that? No!) How can you as a Scrum Master encourage your team to plan the Sprint effectively?

Many teams have difficulties doing task planning before they have thought about the technical concept. To address this challenge, I have a strategy I call "Pair and Share".
PreparationGood preparation is half the battle. This means that coming out of Sprint Planning 1, you should have a selected product backlog ("forecast") that consists of reasonably small stories. Six to 10 items in the forecast is a sign that the stories were small enough (assuming it is a good forecast).

Your team has had the conversations with the Product Owner, the Stakeholders, other Subject Matter experts, etc, and the confirmation is reasonably clear, perhaps in the form of a how-to-demo workflow, or other criteria which can be readily turned into an (automated) acceptance test. If you are still discussing the confirmation during the task planning, you probably have a long meeting in front of you ;-) Having said that, there is a reason the Product Owner should be in the room!
Pair and ShareHere's how it works:

As a Scrum Master, I would take a moment to remind the team about the importance of working according to priority, getting things really done (as opposed to getting a lot of stuff sort of but not really done), and of minimizing work in progress, especially unfinished work at the end of the sprint. The goal for this meeting is not to create the definitive technical concept or task planning, but to create enough of each that the team can start working.

Then timebox Sprint Planning 2, the second half of the meeting, to one hour per week of sprint. So for two weeks, that gives you two hours. Divide that again in two halves, in this case 1 hour each for conceptual work and for task planning.

Have the team pair off. So if you have 6 people in the team, you have 3 pairs. Each pair takes two or three stories (what does this say about how big the stories are?). They have 1/2 hour to come up with their initial technical concept for implementing each story. So they timebox their discussion to 10 or 15 minutes per story.

After the first half hour is up, each pair explains how they want to implement each story to the rest of the team. Short Q&A. You are probably timeboxing the presentation to about 5 minutes per story. The rest of the team can ask questions, so this "share" part builds shared understanding and serves as an initial design review. The discussion may cause the team to rethink their solution, which will influence the task planning.

So now an hour has gone by, and you repeat the process, this time for task planning. Split into pairs (possibly different pairs than the first time), take the top stories, and do 1/2 hour of task planning.

During the final half hour, the team meets in front of the task board. One by one, each pair posts and explains their task planning to the rest of the team.

So now, pairs have thought relatively deeply both about the technical concept and the task planning. The whole team is consulted, and the team is well positioned to work forward as a team to start implementing.

BTW 1 - It may be that the team wants to think more about a particular item before committing to that particular concept. That's OK! Just make a task, "Finalize Design" or whatever.

BTW 2 - How did I come up with this? One of my first teams asked themselves this very question, and this is what they came up with! It worked beautifully! So if this doesn't feel right for your team, give them the goals for the meeting and ask them how they want to do it! Maybe you should even do that first!
Categories: Blogs

Test Driven Organizational Change

Agile Tools - Fri, 09/12/2014 - 08:34

change-20272_640

Let’s just say I was testing the bounds of society. I was just curious. -Jim Morrison (1943 – 1971)

I’ve been contemplating experimenting with some change, but I’m not really sure what is going to work and what won’t. In some ways that dilemma mirrors my coding style. Often when I embark on a project, I’m not entirely clear whether or not what I’m doing will work or not. I mean, I think it will work…but I’m really not absolutely positive. When I code…stuff happens.

I guess I could be accused of rushing into coding without taking care to fully think the problem through. But when I’m swept up in the moment, I want to run with the momentum I have. Call me impulsive. I admire others who have the self discipline to worry through the analysis before they get started, but that’s just not me.

That’s why Test Driven Development has been such a lifesaver for me. It forces me to think about what I’m trying to accomplish before I write the code. It gives my approach a little rudimentary discipline, rather than simply stampeding into the code. Moo.

The question is, can I use TDD to help with organizational change? What would that look like? In order to do TDD we have to start by asking ourselves what the expected outcome of this process or change is. In terms of team performance, that might mean a change among many different metrics (i.e. velocity, throughput, etc.). So first you set up the test: what would the desired outcome of the change be? More software? Happiness? Safety? Openness? Joy? Perhaps it is the absence of something?

Example Change: I want to bring more openness to new ideas to our work.

Next, what are the things that would indicate success? A change in the number of releases? A subjective rating of mood? Maybe a count of unsolicited ideas? Keeping a resistance index (a count of protests per session)? A count of positive/supportive statements. Basically we are looking for some kind of measure that might give us an indication that we are passing our test.

Example Test #1: I will count new ideas that come up in team meetings on a daily basis – If the count is greater than 10, then the test passes

 

Wacky thought: would it be possible to measure all behavior change in relation to changes in code? How would a subjective notion like enhanced social safety within the team be reflected in the code base? Whoa…I think I just bent something important in my head when I bumped into that last thought.

Of course, just like for code, you probably wouldn’t write just one test for any given change. Like code, change is complex, so we are going to be well advised to create multiple tests for any given single proposed effort.

Example Test #2: I will count the number of new ideas that get shot down daily – if the count is less than 3, then the test passes

Great, now we have some tests, what next? Well in TDD we run the tests first and verify that they all fail. Yes, Martha, all the tests are red. Good! Now, and only now are we ready to create change.

Example Test Run: Day one, test 1: result is 4 new ideas – test fails. test 2: the result is 4 – test fails. We are red.

So we put our change initiative into place. But wait – we must keep in mind rule #1 of test driven development: do only the very simplest thing to pass the test. What does that mean? Well if you want people to be happy, what’s the very simplest thing we could do? Would you go to HR and initiate some sort of peer reward system complete with executive buy-in and a roll out program with sensitivity training? Or…would you make a point each day of telling someone how much you genuinely appreciate working with them? Remember, rule #1: KEEP IT SIMPLE!

Example Change: Add a new rule to the team agreement – you can’t say “no” to a new idea.

Then we run the tests again. Where do we fail? Where do we pass? Now we might have some interesting information!

So, before I forget, there is one last thing we should do: refactor. Now we need to go back and take a look at those tests and see if we can improve them. We also look for ways to improve the changes we made. Maybe instead of telling people how much you appreciate them, you give them a hug instead.

Then just like in TDD, we go back to #1 and repeat.

Of course we can’t call this Test Driven Development because that name is already taken. Maybe we could call it Test Driven Change? TDC…Yeah, that could work. Let’s call it Test Driven Change – if I can get three people to do it, then we’ll call it a movement!

 


Filed under: Agile, Coaching Tagged: Agile, Behavior, change, change management, Coding, TDD, Test Driven Development, Testing
Categories: Blogs

The Agile Reader – Weekend Edition: 09/12/2014

Scrumology.com - Kane Mar - Fri, 09/12/2014 - 04:39

Edit: I’ve noticed a lot of the Kindle-spam that’s suddenly been appearing. I’ve updated my search rules and edited this post to remove the spam. You can get the Weekend Edition delivered directly to you via email by signing up http://eepurl.com/0ifWn.

The Weekend Edition is a list of some interesting links found on the web to catch up with over the weekend. It is generated automatically, so I can’t vouch for any particular link but I’ve found the results are generally interesting and useful.

 

Categories: Blogs

Helping Your PMO Help You

Leading Answers - Mike Griffiths - Fri, 09/12/2014 - 03:38
Do any of these traditional PMO scenarios match your agile team experiences? Your traditional PMO is so laughably outdated that most agile projects ignoring them; other projects produce token deliverables to appease them, but these bear little resemblance to anything... Mike Griffiths
Categories: Blogs

Cost, Value & Investment: How Much Will This Project Cost? Part 2

Johanna Rothman - Thu, 09/11/2014 - 23:12

This post is continued from Cost, Value & Investment: How Much Will This Project Cost, Part 1

We’ve established that you need to know how much this project will cost. I’m assuming you have more than a small project.

If you have to estimate a project, please read the series starting at Estimating the Unknown: Dates or Budget, Part 1. Or, you could get Essays on Estimation. I’m in the midst of fixing it so it reads like a real book. I have more tips on estimation there.

For a program, each team does this for its own ranked backlog:

  • Take every item on the backlog and roadmap, and use whatever relative sizing approach you use now to estimate. You want to use relative sizing, because you need to estimate everything on the backlog.
  • Tip: If each item on the backlog/roadmap is about team-day or smaller, this is easy. The farther out you go, the more uncertainty you have and the more difficult the estimation is. That’s why this is a tip.
  • Walk through the entire backlog, estimating as you proceed. Don’t worry about how large the features are. Keep a count of the large features. Decide as a team if this feature is larger than two or three team-days. If it is, keep a count of those features. The larger the features, the more uncertainty you have in your estimate.
  • Add up your estimate of relative points. Add up the number of large features. Now, you have a relative estimate, which based on your previous velocity means something to you. You also have a number of large features, which will decrease the confidence in that estimate.
  • Do you have 50 features, of which only five are large? Maybe you have 75% confidence in your estimate. On the other hand, maybe all your features are large. I might only have 5-10% confidence in the estimate. Why? Because the team hasn’t completed any work yet and you have no idea how long your work will take.
Technical Program with Communities of Practice

Technical Program with Communities of Practice

As a software program team, get together, and assess the total estimate. Why the program team? Because the program team is the cross-functional team whose job is to get the software product to done. It’s not just the software teams—it’s everyone involved in the technical program team.

Note: the teams have to trust Sally, Joe, Henry and Tom to represent them to the software program team. If the teams do not, no one has confidence in any estimate at all. The estimate is a total SWAG.

The delegates to the program team know what their estimates mean individually. Now, they “add” them together, whatever that means. Do you realize why we will call this prediction? Do Sally, Joe, Henry, and Tom have feature teams, service teams, or component teams? Do they have to add time for the experiments as they transition to agile? Do they need to gain the trust of their management? Or, are they already experienced agile feature teams?

The more experienced the teams are at agile, the better the estimate is. The more the teams are feature teams, the better the estimate is. If you are new to agile, or have feature teams, or have a mixed program (agile and non-agile teams), you know that estimate is way off.

Is it time for the software program manager to say, “We have an initial order-of-magnitude prediction. But we haven’t tested this estimate with any work, so we don’t know how accurate our estimates are. Right now our confidence is about 5-10% (or whatever it is) in our estimate. We’ve spent a day or so estimating, because we can spend time delivering, rather than estimating. We need to do a week or two of work, deliver a working skeletong, and then we can tell you more about our prediction. We can better our prediction as we proceed. Remember, back in the waterfall days, we spent a month estimating and we were wrong. This way, you’ll get to see product as we work.”

You want to use the word “prediction” as much as possible, because people understand the word prediction. They hear weather predictions all the time. They know about weather predictions. But when they hear estimates of work, they think you are correct, even if you use confidence numbers, they think you are accurate. Use the word prediction.

Beware of These Program Estimation Traps

There are plenty of potential traps when you estimate programs. Here are some common problems:

  • The backlog is full of themes. You haven’t even gotten to epics, never mind stories. I don’t see how you can make a prediction. That’s like me saying, “I can go from Boston to China on an airplane. Yes, I can. It will take time.” I need more data: which time of year? Mid-week, weekend? Otherwise, I can only provide a ballpark, not a real estimate.
  • Worse, the backlog is full of tasks, so you don’t know the value of a story. “Fix the radio button” does not tell me the value of a story. Maybe we can eliminate the button instead of fix it.
  • The people estimating are not the ones who will do the work, so the estimate is full of estimation bias. Just because work looks easy or looks hard does not mean it is.
  • The estimate becomes a target. This never works, but managers do it all the time. “Sure, my team can do that work by the end of Q1.”
  • The people on your program multitask, so the estimate is wrong. Have you read the Cost of Delay due to Multitasking?
  • Managers think they can predict team size from the estimate. This is the problem of splitting work in the mistaken belief that more people make it easier to do more work. More people make the communications burden heavier.

Estimating a program is more difficult, because bigness makes everything harder. A better way to manage the issues of a program is to decide if it’s worth funding in the project portfolio. Then, work in an agile way. Be ready to change the order of work in the backlog, for teams and among teams.

As a program manager, you have two roles when people ask for estimates. You want to ask your sponsors these questions:

  • How much do you want to invest before we stop? Are you ready to watch the program grow as we build it?
  • What is the value of this project or program?

You want to ask the teams and product owners these questions:

  • Please produce walking skeletons (of features in the product) and build on it
  • Please produce small features, so we can see the product evolve every day

The more the sponsors see the product take shape, the less interested they will be in an overall estimate. They may ask for more specific estimates (when can you do this specific feature), which is much easier to answer.

Delivering working software builds trust. Trust obviates many needs for estimates. If your managers or customers have never had trust with a project or program team before, they will start asking for estimates. Your job is to deliver working software every day, so they stop asking.

Categories: Blogs

Intel Case Study: 8 Trains in 2 months

Agile Product Owner - Thu, 09/11/2014 - 21:34

At Agile Israel 2014 , SPC Yariv Weltsch-Cohen from Intel MDO presented  a case study which recaps their journey into lean-agile transformation using SAFe to launch their first Agile Release Trains.

Intel wanted to standardize the planning and execution process they used to deliver programs for testing and categorizing their chips on different platforms. Scrum was their mode of work for a few years, and SAFe gave them a way to scale up to a program level. They saw this as a natural next step in their lean-agile evolutionary ladder, and a way to accommodate big organizational change. Being Intel, they didn’t just dip their toe into the water. Within 2 months they successfully deployed 8 Agile Release Trains across different geographies. What’s not mentioned in the study, but is noteworthy, is that within another quarter the 8 ARTs became 12 ARTs (~1500 employees) supporting the entire Intel product line.

The 28-page briefing provides their basis for choosing SAFe, and some interesting Q1 release results and conclusions. A few highlights:

• 1st RP is A LOT of effort, afterwards gets much easier.

• Predictability on track for 80% goal

• RP using SAFe recipe helped highlight dependencies and risks (even showstoppers) far in advance of what they saw before.

• Business Owners should take full SAFe training

• Scrum of Scrums is a critical ceremony—based on number of dependencies and learning throughout the PI.

Many thanks to Intel’s Yariv Weltsch–Cohen for spearheading such an ambitious launch and for taking the time to capture their experience and share it with the rest of us.

You can download the study here.

Stay SAFe,
–Dean

Categories: Blogs

Agile Cambridge, Cambridge, UK, October 1–3 2014

Scrum Expert - Thu, 09/11/2014 - 18:12
Agile Cambridge is a three-day conference that is focused on Agile software development. The conference mixes tutorials, experience reports and case studies. Some of the keynotes of the 2014 edition will be presented by Tom Gilb and Nat Pryce & Steve Freeman. In the agenda you can find topics like “Agile! The quick way to build stuff that nobody wants”, “Enterprise Agility: Strategies for Scaling Agile across the Organisation”, “Release Testing Is Risk Management Theatre”, “How to mix together XP and Scrum to enable self organized teams”, “Retrospective Anti-Patterns”, “A systemic ...
Categories: Communities

Ten at Ten Meetings

J.D. Meier's Blog - Thu, 09/11/2014 - 17:54

Ten at Ten are a very simple tool for helping teams stay focused, connected, and collaborate more effectively, the Agile way.

I’ve been leading distributed teams and v-teams for years.   I needed a simple way to keep everybody on the same page, expose issues, and help everybody on the team increase their awareness of results and progress, as well as unblock and breakthrough blocking issues.

Why Ten at Ten Meetings?

When people are remote, it’s easy to feel disconnected, and it’s easy to start to feel like different people are just a “black box” or “go dark.”

Ten at Ten Meetings have been my friend and have helped me help everybody on the team stay in sync and appreciate each other’s work, while finding better ways to team up on things, and drive to results, in a collaborative way.  I believe I started Ten at Ten Meetings back in 2003 (before that, I wasn’t as consistent … I think 2003 is where I realized a quick sync each day, keeps the “black box” away.)

Overview of Ten at Ten Meetings

I’ve written about Ten at Ten Meetings before in my posts on How To Lead High-Performance Distributed Teams, How I Use Agile Results, Interview on Timeboxing for HBR (Harvard Business Review), Agile Results Works for Teams and Leaders Too,  and 10 Free Leadership Tools for Work and Life, but I thought it would be helpful to summarize some of the key information at a glance.

Here is an overview of Ten at Ten Meetings:

This is one of my favorite tools for reducing email and administration overhead and getting everybody on the same page fast.  It's simply a stand-up meeting.  I tend to have them at 10:00, and I set a limit of 10 minutes.  This way people look forward to the meeting as a way to very quickly catch up with each other, and to stay on top of what's going on, and what's important.  The way it works is I go around the (virtual) room, and each person identifies what they got done yesterday, what they're getting done today, and any help they need.  It's a fast process, although it can take practice in the beginning.  When I first started, I had to get in the habit of hanging up on people if it went past 10 minutes.  People very quickly realized that the ten minute meeting was serious.  Also, as issues came up, if they weren't fast to solve on the fly and felt like a distraction, then we had to learn to take them offline.  Eventually, this helped build a case for a recurring team meeting where we could drill deeper into recurring issues or patterns, and focus on improving overall team effectiveness.

3 Steps for Ten at Ten Meetings

Here is more of a step-by-step approach:

  1. I schedule ten minutes for Monday through Thursday, at whatever time the team can agree to, but in the AM. (no meetings on Friday)
  2. During the meeting, we go around and ask three simple questions:  1)  What did you get done?  2) What are you getting done today? (focused on Three Wins), and 3) Where do you need help?
  3. We focus on the process (the 3 questions) and the timebox (10 minutes) so it’s a swift meeting with great results.   We put issues that need more drill-down or exploration into a “parking lot” for follow up.  We focus the meeting on status and clarity of the work, the progress, and the impediments.

You’d be surprised at how quickly people start to pay attention to what they’re working on and on what’s worth working on.  It also helps team members very quickly see each other’s impact and results.  It also helps people raise their bar, especially when they get to hear  and experience what good looks like from their peers.

Most importantly, it shines the light on little, incremental progress, and, if you didn’t already know, progress is the key to happiness in work and life.

You Might Also Like

10 Free Leadership Tools for Work and Life

How I Use Agile Results

How To Lead High-Performance Distributed Teams

Categories: Blogs

Agile Volunteering, Rally Style

Rally Agile Blog - Thu, 09/11/2014 - 17:00

Rally Onboarding Bootcamp: Class of June 2014

“Rally truly practices what it preaches. Volunteering at There With Care touched my heart and made me proud that the company I work for is helping such a wonderful organization. It was amazing how we pulled together as a team and incorporated our Agile training from earlier in the day into our give-back project.” — Terri Barrowcliff, Customer Relationship Manager, Rally Onboarding Bootcamp, June 2014

During my first year at Rally, we’ve experienced exciting growth as a company. When I started in August 2013, we had about 400 people worldwide. Today, we’re over 500 and still growing. With so many people joining the company, we’re continuously refining our onboarding process — adapting it to focus on what newcomers really need to know to succeed at Rally, and introducing a strong dose of company culture. Each month, new employees from around the globe come to our Boulder headquarters to experience Onboarding Bootcamp, Rally style.

Giving back to the communities in which we live and work is among the values on which Rally was founded and holds dear (see 1%: Small Percentage, BIG Impact). Another of our core values, as you might expect, is to Live Agile. So we challenged ourselves to combine the two: create an impactful community service activity that instills the importance of giving back our time and talents that’s also a hands-on learning opportunity in Agile practices. 

I reached out to Jodee Spalding, Volunteer Director at There With Care, a Boulder-based nonprofit organization that provides fundamental support services to families and children facing critical illness. I knew that There With Care relies heavily on volunteers to deliver its services and found a willing partner to customize a program for Rally. With Jodee’s help we quickly identified an important need that Rally could fulfill.

“Easy Meal Care Bags are essential to the parents and caregivers of children being treated in the hospital. Instead of leaving for meals, loved ones can stay at the child’s bedside to provide comfort and support, and ensure they don’t miss an opportunity to speak to the child’s doctor. Now that Rally is sending volunteers once a month to create the bags — and funding the cost — we are able to replenish them as needed, and the families are so grateful.” — Jodee Spalding, There With Care

On their first day of Rally Bootcamp, new employees spend two hours with our Agile coaches learning about Agile concepts, methodology, and practices. Later that afternoon at There With Care, we ask the new hires to practice some of those concepts — such as self-organizing teams, collaboration, and inspect/adapt — when assembling the Easy Meal Care Bags. We provide the product requirements and let the team decide how to get the job done, with the following guidance:

  • Take time to plan the work and organize as a team
  • Focus on quality and process, more than on quantity and speed
  • Limit work in progress (WiP) and watch out for bottlenecks
  • Respond to change over following a plan
  • Consult the Product Owner (Jodee) as much as needed
  • End with a retrospective — what did we learn and what could we do better next time?

Rally Bootcamp participants conduct a midpoint review while assembling Easy Meal Care Bags.

Since February, 134 employees have volunteered at There With Care, contributing a total of 201 hours and creating 425 Easy Meal Care Bags weighing in at 3,188 pounds of food and drinks — lovingly delivered to parents stationed at the bedsides of their critically ill children. A grant from the Rally For Impact Foundation covers the cost of the bag contents, which has totaled nearly $5,000 since the partnership started just nine months ago.

“Just as meaningful as the grant is Rally’s donation of more than 200 volunteer hours from new groups of big-hearted Rallyers lending their compassion each month. In appreciation, we’ve honored Rally with our Inspiration Award, presented to individuals and community partners that have contributed outstanding service to There With Care’s mission.” — Jodee Spalding, There With Care

Geri Mitchell-Brown
Categories: Companies

Knowledge Sharing


SpiraTeam is a agile application lifecycle management (ALM) system designed specifically for methodologies such as scrum, XP and Kanban.