TechEd 2008 notes: How to Make Scrum Really Work

This was a small group, in a small room with a whiteboard, so it was fairly interactive. That means lots of Q&A, which means we jumped all over the place and it looks pretty haphazard in written form. Oh well.

How to Make Scrum Really Work
Joel Semeniuk
Imaginet Resources Corp

Scrum teams are 6.5 times more effective than waterfall teams. (Pity they didn’t cite a source. Anyone got a reference?)

How Scrum works

  • Lots of feedback mechanisms: between team members, re quality of software, with user community
  • Processes that support feedback mechanisms: daily scrums, sprint
    • Sprint = iteration. Generally 2-4 weeks. Design, code, test, deploy.
  • Sprint review: demo to customers, get feedback.
  • Sprint retrospective: Not necessarily every sprint (though that’s debatable, see Juan‘s comments). How did it go? How was the process? Did we feel like this was a successful sprint? What made it successful? If weak, what was the problem? Be constructive. Make sure everybody knows what the team did well.
  • Scrum is a process framework: there are no absolutes beyond the key principles. Continuous process improvement (with the retrospect).
  • House: “You don’t tell your dog to stop peeing on the carpet once a year.”

Roles:

  • Scrum Master. Coach. They take stuff out of the way of the team, to make you more productive. Take away impediments.
  • Team members (everyone involved in building the software, so includes QA, people who set requirements, etc.)
  • Pigs and Chickens
    • Chicken doesn’t have deliverables.
    • Pig has skin in the game.
    • When you make ham and eggs, the chicken is involved, but the pig is committed.
    • In some organizations, at the daily scrum, only the pigs talk. Chickens can observe.
    • Pass a token; only the person with the token can talk.

Is the scrum first thing in the morning? — Do all your devs get in at the same time? (Ha.)

How do you keep a daily scrum short? (Especially when remote.) — Scrum Master is the moderator, and will say, “Rat hole.”

  • What did we do yesterday?
  • What are we going to do today?
  • What are our impediments?

Backlog

  • Bucket of stuff that needs to get done
  • Can assign backlog items to sprints
  • Sprint planning: reconfirm what you have, do decomposition to make it more real
  • If you do internal development, you can plan as you go. If you do contracting or fixed-bid work, you need to spend more time on planning.

Scrum is about what’s next. What about management wanting deliverable dates, when Agile tends to be about discovering stuff as we go?

  • Ken Schwaber: Have a bigger preparation phase, lay out a vision
  • Convince the customer that you can allow change
  • Change is gonna happen
  • We’re allowing the customer to change their mind, by re-prioritizing, changing the schedule, replacing features with others of the same size
  • Prioritizing of backlog is absolutely necessary
  • Track everything: changes in priority, changing out features. Just because we’re doing agile doesn’t mean we throw out best practices about change management.
  • Might be able to win projects even if you refuse to do a fixed bid. Can’t fix all three aspects of the Iron Triangle, which makes for an adversarial customer relationship. Can say, “I understand your budget. We think it’ll be this much. Let’s keep features flexible, and stay aware of the business value of each one.”
  • Sometimes Scrum isn’t the right model, especially when there’s a lack of trust.
  • Aside: Every team should have a nap room.

Suggested story pattern: “As a <role> I want <ability> so that <benefit>.”

Team System plug-ins to help manage sprints electronically:

  • Conchango
  • MSF for Agile
  • Lightweight Scrum Process Template
  • eScrum template (Microsoft)

User stories

  • Three things:
    • What I’m trying to do
    • Conversation about that user story: what fields? what reports? Record that in the work item.
    • Acceptance test, in the terminology of the user.
  • Suggestion: “Sprint 0” = planning sprint.
  • Product backlog: User Stories.
  • Sprint backlog: tasks that need to be done to complete those user stories.

Estimation. One possible technique:

  • Rate each story for:
    • Complexity (1 to 5)
    • Business value (1 to 5)
  • If it’s got a complexity of 5, you must decompose.
  • Rock/paper/scissors-style estimation. If you’re off by more than one, we don’t have the same understanding of the problem.
  • Why use a made-up scale instead of hours? — Don’t want it to turn into a budget for the developers. “Student syndrome”. If it was estimated at a day, the programmer thinks they have a day to do it. Instead, the dev should do the necessary work, no less and no more.
  • Try to discourange single-point estimation. (I think they meant single-axis, which is why they suggest rating both complexity and value. It’s been a few days, though, so I might be remembering wrong.)
  • Another suggestion: minimum / most probable / maximum time.
  • Another suggestion: estimate + certainty.
  • The guy who did order-of-magnitude estimation does hours during execution: how many hours spent, how many estimated hours remaining.

Impediments (obstacles)

  • They have a flag on their work-item database called “Issue”. That seems way too slow-response to me — shouldn’t you just walk over and talk to the customer?
  • Risk management.
  • Mitigate risk. How to lower impact or lower probability?
  • Trigger. When is it not a risk anymore, and now a Problem? What’s the contingency?
  • Mitigations are tasks in your backlog.
  • Can become a rat-hole.
  • Bottom line: anticipate problems.

Scrum of Scrums

  • Each team has their own scrum meeting
  • A few people from each team do a combined scrum, so the teams have some idea of where other teams are

What do you do when your backlog is hundreds of stories long?

  • Consider feature-driven development. Major features, feature sets, features. Structure your backlog that way.

They don’t like teams bigger than 7.

Scrum scaling: “team of teams”. But even so, after about 50 people, scaling on team of teams degrades quickly. FDD scales better.

Amazon: Two-large-pizza rule. A team can’t be bigger than can be fed by two large pizzas. (So, two people, right?)

How to deal with scope creep? — Need a big, burly scrum master. Bring the customer in, lay the cards on the table, and ask what they want to give up. As long as you haven’t started the task, you can change the sprint by trading something out.

Time, Resources, Features: Pick 2.

Side quote: “Drive-by chickens”

So you do the estimates, make the commitment, more requirements emerge, and they don’t want to take more time for them? — Maybe you can’t do agile. Do requirements up front and then change-report the snot out of it.

If your velocity suddenly changes and you figure it out mid-sprint, figure out why. Don’t re-estimate; adjust your velocity.

Some metrics:

  • Stories per sprint
  • Complexity points per sprint
  • Burndown chart

Audience suggestion: Anyone can stop the sprint and call a meeting to resolve something.

End of iteration and not done? — Cover it in the review, move it to the next sprint. Drop from sprint release; remove from the build. That work didn’t get done. Milestones: nothing is 82% done.

If you really don’t want wiggle room at the end of the sprint, put the end of the sprint on a Wednesday. Student syndrome — not thinking about it until the last minute.

TechEd 2008 notes: Busy .NET Developer’s Guide to F#

I’m a bit late getting my Thursday and Friday notes posted. Thursday night was Universal Studios, so I didn’t get any posting done then, and by Friday night I was just plain worn out. So here we go again, starting with Thursday morning.

Busy .NET Developer’s Guide to F#
Ted Neward (talking about the slides)
Neward & Associates
www.tedneward.com

Luke Hoban (doing the demos)
F# Program Manager
blogs.msdn.com/lukeh

F# is a functional, object-oriented, imperative and explorative programming language for .NET.

  • OO you already know.
  • Imperative = sequential execution. C#, batch files, etc.
  • Explorative = REPL loop / interactive prompt. Executing code on the fly in Visual Studio.
  • Functional
    • This doesn’t mean “F# is functional” as opposed to “C++ is dysfunctional”.
    • Mathematical definition of “functions”.
    • f(x) = x + 2. So if you pass 5, you get 7, no matter how many times you do it.
    • Immutable; no shared state.
    • This means we can do some substitution. Can break down into pieces, solve for part of it, put it together and get the right answer.
    • Look to create functions that can be composed into higher-order functions.
    • Very concurrency-friendly.

F#: The combination counts!

  • Strongly typed. Makes sure you didn’t do anything really, really stupid. Historically, compilers have been rather stupid about this: if I say s = "Luke", why do I have to tell the compiler it’s a string? It already knows, after all.
  • Succinct
  • Scalable
  • Libraries
  • Explorative
  • Interoperable
  • Efficient

What is F# for?

  • General-purpose language
    • Can be used for a broad range of programming tasks
  • Some particularly important domains
    • Financial modeling and analysis
    • Data mining
    • Scientific data analysis
    • Domain-specific modeling
    • Academic
  • Speed and power

Install F# addon into Visual Studio

“F# Interactive” window (REPL prompt). This is a dockable window in the IDE. Just type code in. E.g.

1+1;;

Can also highlight code in the code editor and press Alt+Enter, which runs that code in the interactive window; then you don’t need ;; to tell it you’re done. (So what do you do if you use ReSharper and Alt+Enter already does lots of cool stuff? I wonder if keybindings in the editor are language-sensitive.)

// Turn on the significant whitespace option
#light

System.Console.WriteLine "Hello World"

System.Windows.Forms.MessageBox.Show "Hello World"

printfn "Hello World"

The Path to Mastering F#

  • Covered today:
    • Scoping and “let”
    • Tuples
    • Pattern matching
    • Working with functions
    • Sequences, lists, options
    • Records and unions
    • Basic imperative programming
    • Basic objects and types
    • Parallel and asynchronous. Comparing C# examples from MSDN to their F# equivalents.
  • Not covered today:
    • F# libraries
    • Advanced functional/imperative
    • Advanced functional/OO
    • Meta-programming
  • They can’t teach us a programming langugae in 75 minutes. They just want to make us dangerous. Get us to where we can read the examples.

“let” and scoping

Let: binds values to identifiers

let data = 12
let f x =
     let sum = x + 1
     let g y = sum + y*y
     g x
  • No semicolons. Language can figure out where the statement ends. Also makes use of significant whitespace.
  • No parentheses.
  • Type inference. The static typing of C# with the succinctness of a scripting language. We can specify types when we want to be unambiguous. There’s also some generic stuff that can happen.
  • No real distinction between variables and function declarations.
  • Nested functions. sum and g aren’t visible outside the scope of f. So we have additional encapsulation that C# and VB don’t have.
  • Closures.
  • Last value calculated becomes the return value.
  • Immutability (by default).
let PI = 3.141592654

PI <- 4.0

That’s an error: “This value is not mutable.”

  • Is this a property or a field? We don’t care.
  • <- is assignment.
  • You can make something mutable. But they do the right thing, by default, with respect to concurrency.
open System
open System.IO
open System.Net

let req = WebRequest.Create("http://www.live.com")
let stream = req.GetResponse().GetResponseStream()
let reader = new StreamReader(stream)
let html = reader.ReadToEnd()

html
let http(url: string) =
    let req = WebRequest.Create(url)
    use resp = req.GetResponse()
    use stream = resp.GetResponseStream()
    use reader = new StreamReader(stream)
    let html = reader.ReadToEnd()
    html
  • Actually did provide type annotation in the above example. Sometimes it can’t infer the type. This is one such case, because WebRequest.Create is overloaded. These are fairly rare in the bulk of F# code.
    • I’m curious what happens if you don’t annotate this example; that’s a detail they didn’t show. Compiler error?
  • use is like C#’s using block.
    • I’m curious how it knows how big the scope is, i.e., where in the code to insert the call to Dispose.
let html2 = ""
html2 <- http("http://www.live.com")
  • Red squiggle under the second html2. Background compilation. This is why you can hover over an identifier and see its type.
  • If you really want to make it mutable:
let mutable html2 = ""
html2 <- http("http://www.live.com")

Lists, Options and Patterns

  • Lists are first-class citizens
  • Options provide a some-or-nothing capability
  • Pattern matching provides particular power
let list1 = ["Ted"; "Luke"]

let option1 = Some("Ted")
let option2 = None

match Option1 with
| Some(x) -> printfn "We got an %A" x
| None -> printfn "Nope, got nobody"
  • Semicolons as delimiters inside lists. Yes, it’s silly that it’s not comma. Red squigglies will help you figure out when you get it wrong.
  • Option type: you can either have some of a particular value, or none. (This looks pretty similar in intent to nullable types in C#.)
    • Looks like Some and None are predefined as part of the language or the library, though they didn’t explicitly go into this.
  • Some is a generic; it can contain any type. Generics are very lightweight, almost invisible.
  • Pattern matching. Note that it not only matches Some(x), it also extracts the value (x) for us to use.

Functions

  • Like delegates + unified and simple
(fun x -> x + 1)

let f x = x + 1

let g = f

val g : int -> int
  • First: Anonymous function.
  • Second: same thing, but we’re giving it a name.
  • Third: creating another identifier that’s bound to the same value as f.
    • We’re starting to treat functions as values.
    • This lets us do interesting things like higher-order functions, which are very difficult to express in a language like C#.
    • Nobody’s saying you can’t do this in C#. But F# syntax is more succinct, and sometimes a little bit more powerful.
    • Nobody’s saying you need to stop using C#. If you want to continue creating tomorrow’s legacy code, nobody’s going to stop you.
  • I think the fourth one isn’t actually code, but rather the thing F# displays when it’s telling you the type. I didn’t quite catch that bit, though, so I’m not sure.

Lists

let sites = ["http://live.com"; "http://yahoo.com"]
let sites' = "http://live.com"::"http://yahoo.com"::[]
let sites'' = ["http://live.com"] @ ["http://yahoo.com"]
  • :: means “prepend this element to this list”
  • @ appends two lists.
  • Names can have prime and prime-prime suffixes.

Arrays

let sitesArray = [|"http://live.com"; "http://yahoo.com"|]
  • Arrays can be useful. They’re still immutable, but can be very performant.
  • They did not go into any details on how arrays are different from lists.

Tuples

let nums = (1,2,3)
let info = (1,true,"hello")
  • Packages up some data. Type is reported as int * int * int.

Computed lists

[ 0 .. 10 ]
[ for i in 0 .. 10 -> (i, i*i) ]
[ for i in 0 .. 20 -> (i, sin(float(i)/20.0*Math.PI)) ]
  • First: just returns a list
  • Second and third: list of tuples

Example: Web crawling

open System.Text.RegularExpressions

let linkPath = "href=\s*\"[^\"h]*(http://[^&\"]*)\""

let msft = http("http://www.microsoft.com")

let msftLinks = Regex.Matches(msft, linkPat)

[ for m in msftLinks -> m.Groups.[1].Value ]

let getLinks (txt:string) =
    [ for m in Regex.Matches(txt,linkPat) -> m.Groups.[1].Value ]

let getFirstLink html =
    let links = getLinks html
    match links with
    | [] -> None
    | firstLink :: _ -> Some firstLink

Unions and pattern matching

type Expression =
    | Num of int
    | Neg of Expression
    | Add of Expression * Expression

let expr = Add(Add(Num 1, Neg(Num 2)), Num 3)
  • Unions are like an enum, but one that can carry data along with it. Very succinct and clear.
let rec evaluate expr =
    match expr with
    | Num(n) -> n
    | Neg(e') -> -(evaluate e')
    | Add(e', e'') -> (evaluate e') + (evaluate e'')

evaluate expr
  • let rec means it’s a recursive function. You have to make that explicit.

Functions and Composition

let htmlForSites = List.map http sites
  • First argument is a function; second argument is the list. Returns a new list with the function results.
  • If you look at the type of List.map, it’s val map : ('a -> 'b) -> 'a list -> 'b list. The prepended ' mean it’s a generic.
sites
|> List.map http
|> List.map (fun x -> x.Length)
|> List.fold_left (+) 0
  • |> is the piping operator.
  • List.fold_left is used to sum all the lengths.
  • Three different kinds of functions:
    • Defined explicitly, with a name: http
    • Anonymous function: (fun x…
    • Operator, passed around and used as data: (+)

GUI and databinding

open System.Drawing
open System.Windows.Forms

let form = new Form(Visible = true,
                    Text = "A simple F# form",
                    TopMost = true,
                    Size = Size(500, 400))

let data = new DataGridView(Dock = DockStyle.Fill)
form.Controls.Add(data)

data.DataSource <- [| ("http://www.live.com", 1) |]
// more stuff to set column headers

let limit = 50
let collectLinks url = getlinks (try http(url) with _ -> "")
  • An array of tuples can be bound to a datagrid. How cool is that?
  • try keyword is used to say “ignore anything that throws an exception”. If F# has anything like try..finally or try..catch, they didn’t demo it today.
let rec crawl visited url =
    data.DataSource <- List.to_array visited
    Application.DoEvents()
    if (visited |> List.exists (fun (site,_) -> site = url))
      or visited.Length >= limit
    then
        visited
    else
        let links = collectLinks url
        let visited' = (url, links.Length) :: visited
        List.fold_left crawl visited' links

crawl [] "http://live.com"

Object Oriented + Functional

#light

namespace Library

type Vector2D(dx:double, dy:double) =
  member v.DX = dx
  member v.DY = dy
  member v.Length = sqrt(dx*dx+dy*dy)
  member v.Scale(k) = Vector2D(dx*k, dy*k)
  • F# doesn’t differentiate between properties and methods. They want you thinking about the problem, not about software engineering.
  • Constructor parameters are in the type declaration itself. That’s the primary constructor that all others defer to, ’cause that’s usually what you do. No wasted syntax initializing the fields; it’s constructor signature, field declarations, and assignments all in one.
  • When you build types in F#, you can see them in C#. X, Y, and Length are properties; Scale is a function.
  • F# doesn’t automatically realize that fields are immutable and it can precompute the length. F# is immutable by default, but it’s hard to figure out how aggressive to be. (That doesn’t make a whole lot of sense based on what I know so far — you have to explicitly say when you want something to be mutable — but I guess there could be more going on somewhere.) If calculating Length is expensive, you have to precompute it yourself, thusly:
type Vector2D(x : float, y : float) =
    let norm = sqrt(x*x + y*y)
    member this.Length = norm
  • That let becomes constructor code.
override this.ToString() = "hello"
  • Intellisense works — type override this. and a completion list pops up.

Case Study

  • The Microsoft adCenter Problem
  • Cash-cow of Search
  • Selling “web space” at www.live.com and www.msn.com.
  • What’s the chance, if I put up a certain ad, that a user will click on it?
  • Internal competition for a better clickthrough-prediction algorithm
  • Winning team used F#

Their observations

  • Quick coding. Less typing, more thinking.
  • Agile coding
  • Scripting. Interactive “hands-on” exploration of algorithms and data over smaller data sets.
  • Performance. Immediate scaling to massive data sets.
  • Memory-faithful
  • Succinct. Live in the domain, not the language. They were able to have non-programmers helping with the code.
  • Symbolic
  • .NET integration

Taming asynchronous I/O

  • Pages of C# code
let ProcessImageAsync(i) =
    async { let inStream = File.OpenRead(sprintf "source%d.jpg" i)
    let! pixels = inStream.ReadAsync(numPixels)
    let pixels' = TransformImage(pixels, i)
    let outStream = File.OpenWrite(...
    do! outStream.WriteAsync(pixels')
    do Console.WriteLine "done!" }

let ProcessImagesAsync() =
    Async.Run (Async.Parallel
                [ for i in 1 .. numImages -> ProcessImageAsync(i) ])
  • let! means “do this asynchronously”
  • Async.Parallel means “do this stuff in parallel, and just make it work”

F# Roadmap

  • May 2008: MS Research F# refresh release
    • Language and libraries clean-up and completion
  • Fall 2008: F# CTP release
    • Language decisions finalized
    • Foundation of full integration into Visual Studio
  • Future: releases with betas and RTM of next version of Visual Studio
    • Either as an add-in or in-the box

Resources

TechEd 2008 notes: Managed Add-In Framework

This looks like a lot of work, but that’s because they’re solving a hard problem (both upward and downward compatibility). Don’t be scared off by the amount of code, though — lower down I have info about a tool they wrote that autogenerates some of the boilerplate code.

Still, it’s a lot of work, and it would take time to wrap your head around it. If all you want to do is delay-load parts of your application, the add-in framework is probably far, far more than you need. It’s for real add-in frameworks, where other people will write add-ins, and the add-ins will be on a different release schedule than your app is (so you need forward and/or backward compatibility).

Migrating Extensibility to the Managed Add-In Framework: Using System.AddIn to Find and Activate Add-Ins in 3 Lines of Code
Jesse Kaplan
Program Manager
Microsoft

Side note: the add-in framework is .NET 3.5 only. So we can’t use it until we drop support for Windows 2000.

Session Objectives & Agenda

  • Intro to extensibility and System.AddIn
  • Hosting in 3 Lines
  • Keeping new host compatible with older add-ins
  • Migrating to System.AddIn

Why Extensibility

  • Let users or third parties add features to your app
  • Turn your app into its own platform. Makes users tied to your app.
  • Unexpected benefit: Componentize your app. Disconnected update cycles.

Types of Extensibility

  • Add-Ins can provide a service to a host
    • Browser content add-ins (Flash, Silverlight, PDF)
    • File-type handlers
    • Media Player: standalone app, often hosted in other apps
  • Host can provide services to add-ins
    • Large application that plug-ins can hook into
    • Classic automation add-ins
    • Office style extensibility

“Version 1” problems

  • Discovery. How do you find the add-ins?
  • Activation
  • Isolation. How do you put it in an AppDomain or a different process, and still communicate with it?
  • Lifetime management
  • Sandboxing
  • Unloading

“Version 2” problems: Problems you don’t know you have until V2. These are really the reason Microsoft developed the add-in framework.

  • Backward compatibility. How do you keep old add-ins working as you change your host?
  • Forward compatibility. How do you let newer add-ins work in older apps?
  • Adding new isolation levels. What if it used to be AppDomain isolation, and you decide to move it to process isolation?

What is System.AddIn?

  • New set of assemblies in .NetFX 3.5
    • System.AddIn
    • System.AddIn.Contract
  • Solves “V1” problems
  • Architecture that makes building the next version as painless as possible

Guiding principles

  • “My” types are never loaded into “your” domain
  • Hosts and add-ins can version independently
  • Make it easy and natural to build your V1 without closing the doors on V2

Three Developers

  • Host developer
  • Add-In developer
  • Object Model (OM) developer: the one who designs the object model that host and add-in communicate through. Often the same person as the Host developer.

Host Developer Experience

  • Hosting add-ins with three lines of code
  • Communicate with add-in as if it were a local object
  • Install: AddInStore.Update(path)
  • Find: IList<AddInToken> tokens = AddInStore.FindAddIns(typeof(IMyAddIn), path)
    • It doesn’t load add-ins or execute any code to return this list.
  • Activate: IMyAddIn addIn = token.Activate(AddInSecurityLevel.Internet);

Add-In Developer Experience

  • Like the boundary wasn’t even there
  • Implement the interface: MyAddIn: IMyAddIn {}
  • Name your Add-In by adding an attribute to the class: [AddIn("My First Add-In")]

Host code:

using System.AddIn.Hosting;
...
AddInStore.Update(PipelineStoreLocation.ApplicationBase);
IList<AddInToken> tokens = AddInStore.FindAddIns(typeof(ICalcAddIn),
  PipelineStoreLocation.ApplicationBase);
ICalcAddIn calc = tokens[0].Activate<ICalcAddIn>(AddInSecurityLevel.Internet);
RunCalculator(calc);

Add-in code:

[AddIn("MyAddIn")]
public class MyAddIn: ICalcAddIn
{
  ...
}

To run it in a separate process:

ICalcAddIn calc = tokens[0].Activate<ICalcAddIn>(new AddInProcess(),
  AddInSecurityLevel.Internet);

Automatically unloads AppDomains and tears down processes as needed. (Can override this for processes, if you want to reuse it.)

No special issues with multithreading.

How many add-in processes are there? A: One per AddInProcess instance you create. Can also use AddInController to query which AddInProcess was used for a given AddIn, so wouldn’t necessarily even need to keep your own reference.

You can choose to activate in the current AppDomain (use the overload that takes an AppDomain), though there are reasons not to do that.

If you use processes, and the host has threads, how does that work? A: Uses standard remoting, which starts a thread for each request. This means you can’t be an STA thread.

The Architecture

  • Letting you build the right abstraction layers right from the start
  • Change object model without breaking add-ins

First cut at the architecture

  • “View” (object-model assembly)
  • Host and AddIn assemblies both consume that same assembly
  • Problem: If you change your interface, you have to rename it. Maybe you can upcast and downcast. Maybe you need to add assemblies.
  • Lots of upcasting and downcasting, type checks, etc.
  • Once you cross an isolation boundary, both host and add-in have to deal with MarshalByRefObject lifetime management.

The Butterfly Architecture: Separate the views and fill in the pipeline

  • Host has host’s view (static dependency)
  • AddIn has addin’s view
  • Contract assembly has another definition of all assemblies, but it’s the only one whose types cross the isolation boundary
  • Adapters on both sides that adapt from the contract to/from the host and addin views
  • Contract is a contract between the adapters, not between the host and add-in
  • You can replace the center, or pieces of the center, without the host or the add-in even being aware of it

Side note: After initiation, there’s not much difference between host and add-in.

Host and add-in can do events back and forth.

  • Host’s view has an interface with some methods. Just a local interface definition.
  • Add-in’s view looks the same, but has an [AddInBase] attribute. Not necessary for host view, because it’s passed to the add-in mangaer directly, so we know what it is.

Contracts

  • [AddInContract]
  • Implements IContract
  • Then the same methods again

View-to-contract adapter

  • [AddInAdapter]
  • Constructor takes an IFoo parameter
  • Descends from ContractBase
  • Implements IFooContract
  • Delegates methods to the add-in that was passed to its constructor

Contract-to-view adapter

  • [HostAdapter]
  • Constructor takes IFooContract, and creates a new ContractHandle on that contract.
    • The ContractHandle is the lifetime management. You don’t use it for anything; you just hang onto it.
  • Implements IFoo

Host V2

  • Old addin is based on addin view V1.
  • Reuse host V2, host view V2, and host side adapter V2.
  • Write an add-in side adapter that converts add-in view V1 to contract V2.
  • When you want to stop supporting those old add-ins, just stop building the cross-version adapter assembly.

Typical use: in v1, you dictate which services your add-in will provide. In v2, you open it up so the add-in can provide other sorts of services as well.

Side note: when they’re reading metadata, they read the assemblies as byte arrays and parse the metadata directly. So there’s no chance of executing any code during that discovery process.

Good news: For many cases, they can autogenerate some code to build all this adapter stuff for you.

Migrating to System.AddIn

  • Break compatibility. Old add-ins won’t work.
  • Dual-mode extensibility. App can talk to old add-ins through its old APIs, and new ones through System.AddIn.
  • Turn old interface into a view.

Can your legacy object model (OM) be a System.AddIn OM?

  • System.AddIn restrictions are really just isolatable OM restrictions
    • If you already isolate, should be smooth
    • Interop assemblies already conform to these rules
    • Their blog has details

Three mechanics for backwards compatibility (if you are able to migrate)

  • Retain your existing discovery system
  • Use FindAddIn (as opposed to FindAddIns) to bridge the gap. Instead of a directory name, it takes an assembly filename and some type info. So they don’t need the AddIn attribute.
  • Add the [AddInBase] attribute to your legacy object model. Otherwise leave the assembly the same, including assembly version. (File version can change.)
  • Build your adapter.

Other Add-In Features

  • Displaying UI across isolation boundaries
    • Your clicks actually go straight into the add-in AppDomain
    • Relies on WPF to do the magic (working to see if it can be done all WinForms in the future)
  • Automatic pipeline generation
    • Meant for v1. Doesn’t know how to do V1-V2 adapters.
    • Generates adapter source code for you, and adds projects as needed
    • This isn’t part of a release; it’s a project on CodePlex
    • Library exposed both as VS add-in and as command-line tool

Resources

Custom exception types: Possible to do, but more difficult. Recommend that you stick with system exception types and pass data to them. If you need to do your own exceptions, it’s best for your adapter to catch and adapt the exception, so you’re never loading their types into your appdomain.

After the session, I asked whether the DLR and duck typing, e.g. with IronRuby, would make some of this easier, because then (assuming your duck typing was forward and backward compatible) you could get rid of a lot of the intermediate translation layers. He said there were some people currently working to figure out how to do cross-AppDomain DLR calls. So no, at this point, that wouldn’t make it any easier. Too bad.

TechEd 2008 notes: Implementing Objects for Data Binding

This, he advised us, was an advanced, specialized talk. It wasn’t about how to use databinding to create UIs; it was more about how to make your objects support databinding, especially in WinForms.

Implementing Objects for Data Binding
Rockford Lhotka
Principal Technology Evangelist
Magenic

His focus: how to make OO work under various Microsoft technologies. As time has gone, our lives have gotten much easier, but as you dig in, you find the warts and gotchas.

Data Binding

  • ASP.NET Web Forms
    • Simplest, least capable model
  • WPF
    • Interactive, but simple model
    • Lacks full functionality
  • Windows Forms
    • Interactive model with high functionality
    • Most complex model
    • If you support Windows Forms, you (almost certainly) support everything else. (WPF is diverging a tiny bit — Rocky sees more of this than any of us will.)

Rocky maintains the CSLA.NET open-source project, which already does all the plumbing for databinding to work. He didn’t set out to become a databinding guru; he just found that it took a lot of time, and was worth sharing.

He has a friend who got fed up and wrote his own databinding framework. Rocky didn’t, because he thought Microsoft got really, really close in .NET 1.1. He thinks they did get better in .NET 2.0, and yet it still has holes.

This will deal with .NET 2.0+. Changes to databinding are largely stalled at this point, with little or none changed after 2.0, because MS is focusing on WPF, and the WPF databinding story is very good (and yet it still has holes).

Architecturally, the goal should be to have zero lines of code in the GUI. We’re not there, even with WPF (though we’re tantalizingly close).

  • How rapidly does your database change? …Not very fast.
  • How rapidly do your business rules change? …Some, but the big things change slowly.
  • But UI changes all the time.
    • Users don’t help. “This is too complex! Too much clutter! Can’t you make it into a wizard?” “This wizard is too awkward. Can’t you make it one page?”
    • Users can’t make up their minds, and technology keeps changing.
    • There’s no code more expensive than the code in the GUI.

Databinding is the main tool MS gives us to get rid of code in the GUI. It’s a very clear, interface-based abstraction. That’s why it’s so important.

Property Change Notification

  • When your object changes, it should tell somebody.
  • History: In .NET 1, MS tried to tell us not to worry, that they’d take care of it all: change it here, we’ll update it everywhere for you. But that doesn’t take care of indirect changes, like with calculated fields. So there was a convention for magically-named events that they would listen to; but they refresh ALL the fields, so if you do the Right Thing and fire four change events, all the GUI refreshes four times. So you want to work around that and only fire one, but there’s another wrinkle: databinding only listens to properties that are actually bound to controls, and the control has to be visible. Nothing wrong with having a size of 0x0, though. (I can already see the problems with tab order, and…)
  • In .NET 2, MS formalized this with: (most of these will be in System.ComponentModel)
    • INotifyPropertyChanged. Forces you to raise an event called PropertyChanged. Much more discoverable… but all the same idiosyncracies are true to this day.
    • INotifyPropertyChanging. New with LINQ. Not used in databinding, at least not yet. Data context object in LINQ to SQL uses it.
    • Force declaration of notification events

Field Refresh Issue

  • If your property has a setter that does something.
  • When you type into a text box and tab out of it, the value is pushed down into the object. If your setter does some rules, like uppercasing the value, the GUI will not display the changed value, even if you raise PropertyChanged?
  • Windows Forms
    • There’s an optimization.
    • When they get PropertyChanged, they refresh all the fields except the one you just edited.
    • Solve by handling event on BindingSource
  • WPF
    • Doesn’t refresh everything. Only refreshes the property that you said was changed.
    • Same optimization: their assumption is that nobody writes code in the set block.
    • Solve by always using a ValueConverter

Demo

  • You must fire PropertyChanged in your property setter. Otherwise you can set the property and the GUI won’t refresh, even though the backing object is changed.
  • So you shouldn’t bind automatic properties.
  • If your property setter doesn’t save the exact value (i.e., if it does some validation or range checking), the GUI won’t see it.
  • WPF binding: Text="{Binding Path=Value1}"
  • Works fine unless the code is changed indirectly.
  • WinForms workaround: hook an event on BindingSource and manually refresh the display.
  • WPF workaround: Value converters (things that implement IValueConverter).
    • Convert(…) and ConvertBack(…). Convert puts the value into the UI; ConvertBack puts it back into the object. This is how you e.g. format dates.
    • It turns out that if you have a value converter, WPF databinding will always refresh the display. So you can make a value converter that just does return value; from both methods.
    • IdentityConverter
    • Change XAML to Text="{Binding Path=Value3, Converter={StaticResource IdentityConverter}}"
  • So how does your UI developer know whether or not to use the IdentityConverter? A: They can’t know, so they should always have a value converter on every binding: either a real one to do formatting and parsing, or an identity converter.
  • WinForms binding: this.dataBindingSource.BindingComplete += handler, and handler does e.Binding.ReadValue();.
  • dataBindingSource is a .NET 2.0 DataBindingSource component. He actually dragged one of his objects onto the form, and the designer created the DataBindingSource for him.
    • DataBindingSource collects mystical stuff that was already there, and makes it more visible.
  • CSLA puts this into an extender control; otherwise you need to do this in every screen.

Events and Serialization

  • Event handlers cause forward references
    • Your object ends up referencing the event handler
  • BinaryFormatter follows / serializes all references
    • Unless marked as NonSerialized
  • Many event handler objects aren’t serializable (Form, Page, etc.)
  • Marking an event NonSerialized does nothing
    • You need to mark the backing field created by the compiler
  • NetDataContractSerializer in WCF is very similar
  • BinaryFormatter serializes private fields, not properties (by default)
  • What if a field references another object?
    • Serializes that other object
  • What if the field points to an object that can’t be serialized?
    • Boom (with reverb). SerializationException. That’s what you would expect.
  • Events: if the form hooks your event (e.g. because you’re doing databinding), you have a delegate field behind the scenes that refers to the form. So you can’t serialize it.
  • NonSerialized attribute says “don’t bother trying to serialize it”, but an event is not a field.
  • Solution: declare your event as a custom event, and manually define the backing field. (Or in C#, just put [field: NonSerialized] on the event. Rocky doesn’t like that syntax and would prefer to add the extra dozens of lines of code for every event; I’d go for the simplicity of the one-line fix.)

Lists and Collections

  • Windows Forms or WPF
    • IBindingList. ListChanged event, searching, sorting.
    • BindingList<T>. Already implements all the interfaces necessary for databinding to Just Work in WinForms.
  • WPF only
    • INotifyCollectionChanged. Subset of IBindingList: more like IPropertyChanged. “I will notify you if the list changed.”
    • ObservableCollection<T>, which implements INotifyCollectionChanged but not all the other databinding stuff.
    • IEditableCollectionView
  • So you just implement both, right? But WPF honors BOTH! So if you implement both, and then remove an item from a list, the UI removes two items.
  • Implement one or the other, not both.
  • Any behavior in the WPF one that’s not in BindingList? A: No.
  • Any benefit to using ObservableCollection<T> in WPF? A: If you’re already using BindingList, no.
  • BindingList<T> requires that the class have a public default constructor. What if your object doesn’t have one, for any number of reasons?
    • Add a class that descends from BindingList<Data>, sets AllowNew from the constructor, and overrides AddNewCore().
    • If you set AllowNew to true, you must override AddNewCore().
    • Inside AddNewCore, you must do three things:
      • Create a new instance.
      • Add the object to the collection.
      • Return it.

Validation Error Support

  • IDataErrorInfo
    • This is how your object can tell databinding whether each property is valid, and whether the object at large is valid.
  • Simple, but of course idiosyncratic: if you do it the wrong way, life is not so much fun.
  • Interface makes you add two properties: Error, and an indexer based on column name (both return a string). If you return an empty string or a null, it means you have a problem and the string is the human-readable reason why.
  • Every time a field changes, not only do the fields get refreshed, so does the error info. So it can get called over and over again. Be very conscious of performance: you can’t do anything here that takes any time.
  • Recommendation: check your rules when you set the property.

Supporting In-Place Grid Editing

  • IEditableObject, which is a mess
    • BeginEdit (“I might need you to undo yourself, so take a snapshot of your state”)
    • EndEdit may be called (“Commit the changes”)
    • CancelEdit (“Revert”)
    • Ridiculously idiosyncratic.
    • The binding system may call BeginEdit many times; you should only honor the first.
    • They may never call EndEdit. If so, you should sort of assume it was called.
    • Best way to handle this when you’ve got master/detail bindings: hook CurrentChanged on the master BindingSource, and call EndEdit() on the detail.

All code will be available via TechEd and via Rocky’s Web site.

TechEd 2008 notes: Design and Testability

Design and Testability
Design Dilemmas in the Real World
Roy Osherove
Typemock
Blog: ISerializable.com (will have slides there)

  • Dilemmas that he’s faced, we’re probably starting to face, Microsoft is facing
  • Many have to do with change
  • Design has changed very little in the last few years, but maybe it’s time for a new thought, or some new compromises, or lack of compromises

Has been on two sides of the same coin

  • Pure design, dependency injection, hardcore freaks
  • Being pragmatic
  • What you can do about testability when tooling is not available to help you (or you choose not to use it)
  • Benefits of testable designs

Agenda

  • Why should I care about testability?
  • Defining a testable system
  • Examples of implementing and refactoring testable code
    • Extract interface, virtual methods…
    • Dependency injection and IoC containers
  • Legacy code, and what happens when you can’t change your design
  • Silver bullets
  • Why current systems make this hard
  • Patterns

Me Me Me

  • The Art of Unit Testing
    • ArtOfUnitTesting.com
  • Typemock
    • Next generation isolation platform (Isolator)
    • Next generation testing tools (shhhh…)
    • Some things are changed, some are a little more powerful, some things feel a little weird

Before we start

  • This is just one way to do design
  • Assuming you have experience with NUnit or MS Test

Why should I care?

  • Framework authors
  • Maintainable system. Testing is about quality, and a security net that lets you know when you screw up.
  • Extensible system, like LEGOs.
  • Code quality

Automated unit/acceptance testing is important

  • Helps with regression testing
    • Maintainable system
  • Finds bugs early
    • Code quality
  • Better understanding of requirements
    • Most people write code from the inside out: write the method, without caring about who’s going to be calling it
    • The test is using the API, so you have to think about requirements, design, usability
    • Also means it makes your coding take longer… but code quality and maintenance are better, and release cycle is actually shorter
  • API documentation
  • “Executable” requirements. It’s good for the customers, because they can run actual tests.
  • Big database change — not a big problem.
  • Even bad tests can help more than you think.

Unit level testing requires testability

  • How easily can you…
    • Create a new instance? Do you need to create a configuration file first? Configure a third-party library?
    • Get a consistent result? Do methods have side effects? Talk to a database or Web service?
    • Test just X without Y?
    • Control inputs and outputs from X?
    • Isolate X from its dependencies?

Two kinds of testability

  • Testable application
  • Test enabling framework
    • ASP.NET MVC, WebForms. WebForms code depends on the WebForms framework, which is not test enabled. Much easier to test code built on ASP.NET MVC.
    • SharePoint. Untestable by default: lots of statics, global objects. Testing your logic is almost impossible.
    • MS CRM. Even more horrible than SharePoint.
    • WCF, WF. Not test enablers by default. WF has lots of sealed classes, multiple processes, multiple threads, no places to intervene. Lots has to do with security, but lots has to do with the way things are done.
    • If you’re a framework author, making your framework test-enabled should be one of your main concerns.

What is a unit-testable system?

  • Lets us write good tests easily
  • For each piece of coded logic, a unit test can be written easily enough to verify it works as expected, while keeping the PC-COF rules

PC-COF

  • Partial runs are possible
  • Configuration is not needed
  • Consistent pass/fail result
  • Order does not matter
  • Fast (what is “fast”? We’ll talk about that)

Consistent pass/fail result

  • Can you trust your test?
  • Control of dependencies (you want to test a method, but it starts with a call to a static method e.g. to validate)

Interface-based design

  • Design: Extract interface for Validator
  • Test: send in a “fake” validator
    • He implements with a public field saying what IsValid should return
  • Inject the IPersonValidator via e.g. a constructor parameter
    • OO purists are panicking that you’re letting someone else decide how to do a core part of your functionality

Side note: if you write a test, give it a good name. Don’t call it Test1, Test2, Test3. He will personally choke you.

  • His name suggested naming convention: MethodBeingTested_UnderTheseCircumstances_DoesThis
  • Don’t name it starting with “Test”, because the attribute already tells you it’s a test

This works, but it kind of sucks. You end up with lots of interfaces, and your classes have lots of dependencies.

“Injecting” dependencies

  • Constructor injection
    • Use for dependencies that are not optional.
  • Property injection
    • That means it’s an optional dependency.
  • Factory injection (especially if you already have a factory)
  • Virtual method injection

The dependency problem

  • People just want to use the code that you wrote. They don’t care about passing in a logger and a validator.
  • To create a logger, you need an exception handler and a data writer.
  • Etc.

Inversion of Control containers

  • Kind of like really smart factories. You ask them for a new instance of some type, they’ll look at the constructor’s dependencies, and if you’ve configured it correctly, it’ll know which objects to pass for those dependencies. If those also have dependencies, it handles it recursively.
  • Spring.NET
  • Castle.Windsor
  • StructureMap (not officially released lately, must build from source)
  • Microsoft Unity Application Block — Unlike many other Application Blocks from Microsoft, it doesn’t suck.
  • Very configurable, from XML or from code

Demos: Windsor and Unity

Windsor

  • Create a WindsorContainer
  • Add components — generic syntax. Either give it a class, or an interface and a class.
  • Have to also add the type you’re going to resolve (instantiate).
  • container.Resolve() — constructs something.
  • Some people believe your tests should call the constructor directly with your fake dependencies, instead of using containers from tests.

Unity

  • Create a UnityContainer
  • Call RegisterType
  • Fluent interface — you can chain calls to RegisterType.
  • Don’t have to register the class you’re going to resolve (instantiate).
  • Tries to use the constructor with the most parameters. Gives an exception if the container doesn’t know how to create one of thoes parameters.

Important: Need to make sure everyone uses container.Resolve instead of new.

Fast run times

  • A test that takes one second is not fast.
  • Want someone to be able to get latest version, right-click, and run all the tests. It should be that simple. And all the tests should pass.
  • If they have to wait a long time, they won’t run all the tests.

No configuration needed

  • How easy is it to get latest and run the tests?
  • If a config file is needed, how do you test a bad connection string? It quickly becomes not easy and not fast to write that sort of test.

Solving configuration with override

  • Works if you don’t want to add interfaces
  • Extract dependency into a virtual method
    • This virtual method needs to be the stupidest code you’ve ever written. Absolutely trivial.
  • Class can’t be sealed, so you can’t do this with WCF, WF, SharePoint, etc.
  • Easier; pollutes the code less; but it forces you to make a lot of derived classes in your tests
  • Good for simple scenarios, maybe not when you get more complexity

Test order should not matter for consistent results

  • Some people don’t mind that tests share data
  • If tests share data, you have dependencies between tests
  • That’s BAD, because you’ll kill yourself when you need to maintain tests. You remove a test and something fails. You modify a test and something else fails.
  • Debugging test dependencies is awful. You can spend days on this.
  • If tests use a shared resource (e.g. a database), you need to fix the tests, not the application.
  • Need to restore shared state in TearDown. For databases, create a TransactionScope in SetUp, and Dispose it in TearDown.

Partial runs of tests should produce consistent results

  • Sometimes you want to run only some of the tests. Sometimes tests do take a long time; that’s the real world.
  • Some test frameworks let you re-run just the failed tests.

Are singletons evil?

It depends. .Instance probably is. Getting it from an IoC container, maybe not so much.

  • How do you instantiate it for testing? (And re-instantiate it, e.g. if you modify the configuration that it loads on startup)
  • Shared resource between tests
  • Single Responsibility.
    • There’s a class being held, and the one doing the holding and making sure there’s one instance.
    • Can refactor into testable ones: separate holder to a separate class, or refactor using a container.
      • Unity: RegisterType(instance)
  • Global variables
  • Tight coupling
  • State that lasts forever
  • Threading?

The GOD Method

  • You know it’s important; you don’t know why it does what it does; sometimes it’s cruel to you
  • One huge do-it-all method
  • Prevents maintenance, impossible to test
  • Can’t refactor for testability, because you might introduce bugs. Solution: integration-level tests.
  • Avoid this by design
  • Keep single responsibility principle
  • Calls to little methods

Legacy code

Test Driven Development/Design

  • Tests have to ues a testable class
  • Test-first means testable-design-first
    • Test can later show you how you’d like the API to be used
  • Decoupled design and architecture
  • More control on state simulations

Design Guidelines

  • Avoid BDUF (Big Design Up Front). Tends to result in highly untestable code. Do EDUF (Enough Design Up Front) instead, but your design should be able to change as you go.
  • Interface-based designs. Tend to be easier to understand in terms of roles. A Logger is a role.
  • Try to avoid Singletons
  • IoC containers
  • Avoid GOD methods — use polymorphism instead
  • Virtual by default
  • new X() -> Factory.MakeX(). When you abstract away the creation, you can replace the creation.
  • Single Responsibility for class and method. If our class or method is elaborate and does more than one thing, it’s usually a design smell.

Key points

  • Design for testability leads to agility
    • You need tests when someone changes the requirements
  • Common patterns
    • Recognizing test challenges in the design
    • Refactoring the design for testability
  • Test-driven development leads to a testable design
  • Testable code == well designed, decoupled design

Musical postlude

TechEd 2008 notes: The Gentle Art of Pair Programming

I already know a fair bit about pair programming, but the session description said, “For those already working in a pairing environment, Wendy and Oksana include some novel viewpoints and interesting discussions on familiar topics.” I think that worked out okay — it’s always good to hear how other people are doing agile, and they do a few things differently than we do.

The description also said there would be “interactive and fun games”, but the room was way too big and spread-out for that to work. There also wasn’t much time for things like that once they’d answered all the questions; people were really curious about a lot of things. Questions and answers interspersed below.

The Gentle Art of Pair Programming
Oksana Udovitska
Wendy Friedlander

Usually an interactive session with games and some hands-on practice, but they got put in a lecture room instead, with not enough time for games

Agenda

  • Who are those chicks? (their words, not mine — I just copied the slide)
  • Let’s get to know each other
  • What this pair programming is all about
  • Personalities and Pairing
  • Daily routines
  • It’s all about the team
  • Respect and communication
  • Wrapping it up

Who Are Those Chicks?
Oksana Udovitska and Wendy Friedlander

  • Software developers
  • On cutting edge of agile practices
  • Wendy likes to code nonstop, do things her way, so was hesitant about pair programming initially; but changed her mind after trying it
  • Oksana enjoys pairing more than regular programming, because it’s very social

A Day In Life Of Pairing

  • Morning stand-up
    • This is when you break into pairs and pick up tasks
  • “War room hours”
    • Uninterrupted coding
    • Try not to schedule meetings or get distracted.
    • ~2 hours in morning and ~2 hours in afternoon.
  • Break for lunch, yummy!
    • Pair programming is very intense — very emotionally and intellectually draining. Need breaks. Sustainable pace.
  • More “War room hours”
  • Go home, yippee!

Morning Stand Up

  • Standing by the story board
  • Talk to the board
    • Worked on this story
    • Finished these tasks
    • This is what we have left
  • They switch pairs at stand-up, and again after lunch.
  • Promiscuous pairing: the person who is newest in the task stays on
  • Rotate pairs — don’t always pair with someone who thinks like you. Can use a chart to keep track.

Losing code ownership. Can stand up from a task in the middle, and have someone else take over. Trust that it will be done OK.

May not have personal desks, but there is team space. So you need to like the people you work with — but you can post pictures of your wife all over the place. Little knickknacks. Space Invaders screenshots. It seems scary, but you get used to it.

Also, there are 2-3 hours a day when you’re doing other things: making calls, researching on the Internet, going to meetings.

More than two people in the room; you’re in the same room with the other pairs on the team. They called this “osmotic information”: even if you’re not focused on it, you have some awareness of what others are doing. If another pair seems stuck, you can offer to help. If you’re stuck, you can ask for help. If you need to make a decision that could affect the whole team for the next couple of weeks, you can talk to the group about it. (But try to only interrupt if you need to, because of context switching.)

Do you have to match experience levels? — Surprisingly enough, yes and no. Make sure you both understand what you’re trying to do, but even if you’re not the best person to complete the task, you still can have good ideas on how to approach it, and you learn really fast. Oksana’s experience, as a newbie in a pairing environment, was that she didn’t feel she was dragging anyone down. You immediately learn the things that you need to know.

Depending on who you’re pairing with, it’s your responsibility to customize your behavior or put on a different pairing hat. If one person feels like they’re dragging the pair down, that’s the fault of the more experienced person. (Trading the keyboard often may help with this.)

There is no driver: there’s a typer. Both people should write every line of code. If you do it right, you’re both engaged all the time.

Coding-style conflicts: very different when you’re pairing. Wendy said she writes code in a very different style when she’s pairing than when she’s alone. Oksana pointed out that you can change the code’s style; nothing will stop you except your pair (who will probably point out that you could be writing new code instead). It becomes a lot more fluid, and people tend to start writing code, not necessarily in the same style as everyone else, but in a style that everyone else can read. Anyone can try something new, and if others don’t like it, it’ll get deleted (so don’t take it personally — must be a friendly environment). It becomes really easy to agree; the things that make sense stick around, and the things that don’t make sense don’t stick around, and you don’t even remember who did it.

Don’t you get half as much done when you have two people on the same task? — No, because:

  • More focus
  • Blocked less often
  • More knowledge — people can take vacations without everything else grinding to a halt
  • Compare cost of fixing early vs. fixing after a bug gets into production.
  • Start with a pilot project on something big and risky, and see if the benefit shows.
  • If the team is self-managing (as it should be in an agile shop), just do the pairing. As long as management is happy with the work, try stuff to see if it makes sense. Then reflect on it to decide whether it worked.

How many developers do you need to get this started? — Probably 4-6 developers; 6 is a little large for getting everyone to agree all the time.

What if there’s an odd number of people? — Can work alone, just needs a review afterward. Also lean on continuous integration. Or if you don’t want to work alone, you can work on spikes (research into new technology, doing the quickest, dirtiest proof of concept), or maintain the build server, or review old code.

Velocity: Different pairs of people work at different speeds. So you just have to look at how many story points you average as a team, and know that it won’t be exact. Many agile teams don’t put too much time into estimation, especially long-term estimation (and “three months out” changes every two weeks as the customer changes priorities).

How do you do employee reviews? — Everyone knows everyone’s strengths. Some people are good at coding, some people make the pair happy, some people make the pair unhappy. It becomes a team thing — the team did well, so the team gets a raise. Then maybe, if one person is especially good, they get a little extra.

Becomes a very healthy environment. Don’t have people being pathologically competitive and protective of their code and knowledge.

Documentation: customer-facing documentation only, if needed. No design docs or comments (your tests are your comments). You probably will tend to have a wiki to store knowledge like port numbers, how to set up the build environment, etc.

Do it together? Do it yourself?

  • People are social animals
  • We can do things alone or together
  • Which do you prefer?
  • Learning to communicate with a pair can help you learn how to communicate with customers

What is pair programming?

  • Team effort
    • Everyone participates
    • No heroes
    • Good to put people who are inexperienced in a task on that task
      • Have to be open to failing your commitment because you’re not putting the hero on the task all the time.
  • Collaboration and sharing
    • Knowledge transfers — not knowledge transfer!

Why pair?

  • More interactive
  • Team spirit
  • Confidence
    • Okay to ask questions and show vulnerability
    • Know others agree with your code and like it
  • No more code reviews
  • Readability and consistency
  • Discipline
  • You can take vacation!

Why is it hard?

  • Personal interaction
  • Everyone is unique
  • Less personal space and time
  • Very intense
  • Have to do the wrong thing sometimes to keep the flow going (don’t spend two hours discussing why it’s going to fail — just write it and let it fail)

My way, your way, our way?

  • Talk
  • Compromising isn’t good. You can’t really compromise between two different patterns; they don’t mix. Choose your battles — better to do it in a poor way, but completely. Or try it, show that it can’t work, and then do the other way (and maybe you were wrong and it is good enough).
  • YAGNI
  • Know when to ask the team

Getting started

  • How?
  • Commit. Make sure everyone on the team agrees that it’s worthwhile to try, and try it for at least a week.
  • Switch pairs. Helpful if you’re sitting in the same room, or at least nearby.
  • Can be done remotely, as long as you know you’ve got the technology working (VPN, screen sharing, etc.) But you do lose osmotic information; you don’t know what other pairs are doing. Cameras are helpful. Skype + VNC. Pairing is probably the easiest agile practice to do from home.
  • Know your results.
    • Know how to reflect on what’s working and what isn’t.
    • Don’t be afraid to bring up things that should change.
    • Go around the room, have everyone say something we should keep doing and something we should change.
    • If you’re doing agile, retrospectives are core. Otherwise you’re being dogmatic.

The most important thing

  • Having fun!
  • If the walls are blank and everyone’s staring at the monitors, you’re doing something wrong. Joking, talking, arguing (in moderation).

Respect and communication

  • Communicate
  • Respect your pair
    • Be open to their suggestions
    • If something bad happened at home and you’re in a bad mood, you have to leave it behind
    • Hiring process is really tricky. You need people on your team who will interact well.
  • Express yourself and listen

Knowing when to mentor

  • Pairs not matched
    • It’s rare that one person won’t be mentoring. If you’ve got two experts pairing, they’re probably not experts in the same thing.
  • Frustration
  • Mentoring mindset

They think nine developers is too large for one team — they suggested forming two sub-teams, each working on its own domain, and letting people move between sub-teams.

TechEd 2008 notes: Microsoft Software Licensing and Protection Services

I didn’t know Microsoft even had an API for software licensing. They do, but there’s a lot of stuff it doesn’t do, most of which is supposed to be coming in the next version.

Microsoft Software Licensing and Protection Services
(SLP Services)
Terrence J. Nevins (tnevins@microsoft.com)
Rehan Hamid

Software Economic Models

  • Licensing market: $228B today, growing to $305B by 2010
  • Subscription: $113B for Internet access growing to $200B by 2010; IPTV growing to $17B by 2010
  • Advertising: $27B+ today, $80B+ in 2010
  • Transactional: $10.7B sold on Amazon in 2006; $52B sold on eBay in 2006; $2B in music downloads; $1B in ringtones

Key Challenges for Licensing

  • Fighting piracy and low compliance, reverse engineering
  • Meeting customer demands: try before they buy, subscription models
  • Reducing costs and enabling integration

Big tip

  • Getting started
    • Request an Evaluation (your MSDN subscription key is good for their license services, but don’t use it when you’re playing around — get an eval key instead)
    • Activate your account
    • Use the evaluation key as your “sandbox”
    • Preserve your potent MSDN subscriber key
      • Use MSDN key for commerical use, not for testing
      • One year service subscription
      • A starter set of free activations included

www.microsoft.com/slps/ to request an eval key

PROTECT

  • Protect against reverse engineering, binary patching
  • Balance protection and performance
  • Make it easy for your customers to stay in compliance

Code Protection. You want to use IL and reflection, but you want to protect your IP.

  • Select app to be protected
  • Identify methods to be transformed
  • Transform method IL to SVML
  • Distribute protected app with SVM

SVML — Secure Virtual Machine Language

  • MSIL is easy to reverse engineer. SVML is very difficult to reverse engineer, and unique to your organization.
  • SVM — Secure Virtual Machine. Because SVML is unique to you, your SVM is unique as well.
  • Not obfuscation — transformation.

Developers should drive the decision of which methods to protect. Marketing can drive a lot of the policies, but not method selection.

Browse to folder (“Medical” in the example), select methods to protect, click Protect. Creates a “Medical.Protected” directory with a protected EXE and several DLLs.

There’s also a command-line version for automated builds. Can be integrated with Visual Studio. Can use attributes to specify which methods you want to protect. Not really good MSBuild or VSTS CI integration yet, but they’re working on it.

Every time you call a protected method, it calls into the SVM.

Performance impact: Absolute worst case is thousands of times worse. If you have critical code in tight loops, you’ll want to strategically choose which methods to protect.

Supports .NET 1.1 upwards.

What does it cost? — It’s complicated, and it’s going to change in a month or two anyway.

Can you use the protection without the licensing? — Today yes, after July 28 maybe no.

Can you do this with native code? — You wouldn’t really need the protection, so you’d just be doing the licensing. You can do that; you’ll take a managed-code dependency.

Does the end-user need to have a connection to the activation server? — If you want silent activation, yes. Otherwise, you can save a machine “fingerprint” to a USB stick, walk that to an Internet-connected machine, download a license file onto the USB stick, and walk it back to the disconnected machine.

What goes into the machine fingerprint? — It’s complicated. Don’t use MAC addresses. Processor serial numbers aren’t reliable in multi-processor machines. You need some balance, especially when you start implementing it onto an existing customer base. Keep the honest people honest; think about the end-user experience.

Activate by phone / manual activation without USB key? — It was dropped from the current shipping version. It’s currently lower on the internal priority list, so it’s hard to tell when / whether it will come back. For today, you need a homegrown solution to this.

These solutions have to be reviewed by an MS crypto board any time they don’t use the crypto API. It’s reviewed by 20 pairs of eyes that know crypto inside and out. Obviously it’s not totally secure (once you put it on someone else’s machine, it’s not your code anymore), but it’s probably as reasonably secure as it can be. (Note: this was an acquired company.)

Generating keys

  • Go to Microsoft’s portal, log in
    • Create a product, and specify its name and version
      • Major version is part of license. If you want license keys to be good for a time period but any version (including major upgrades), they think that can be done, but would require followup with their devs.
    • Add features
  • Log into local app
    • In property grid, select the product name you created in the portal
    • Select methods and associate them with features
      • If the app isn’t licensed yet, you get a UI prompting you to activate.
        • What about services (where you can’t show GUI)? — Huh? Licensing a service? Apparently nobody ever thought of that. (WTF?!)
        • Can you make it throw an exception instead of popping up GUI? — There’s some kind of API for that.
        • Can the dialog be branded? — Yes.
        • Can you put the licensing into the MSI? — There’s a demo online for that.
  • Go back to portal and create a key (5×5)
  • User selects “Activate over the Internet”, enters that 5×5 into the dialog
    • Contacts the service, gets back a license file, does its magic
  • If you try to use an unlicensed feature (but you have already activated), you get a dialog saying you can’t do that

Concurrency model: License pooling. This is big and complicated. They don’t do that yet.

When you active or reactivate, usage data gets sent to the server automtically. So you get to know how many times they clicked Print.

Microsoft runs their own license server, but you can run your own in your company. There are really only a couple of reasons to do that: regulation; international laws; federal government.

Limited Windows users can activate, though obviously they can’t install an MSI.

Current version does not support ClickOnce deployment. It’s been discussed but is lower priority.

Their Web site has guidance on privacy issues.

If you want to capture feature usage, the feature has to be in a method that you protect (today, at least).

Interesting note: if you’re an early start-up, it can be really valuable to know how many people activated your product. You can prove, to your venture capitalists, how many people activated from different machines; and because of the fingerprint, you can’t fake it by installing it 42 times on the same box.

Is there a Web service for the portal? — Currently no, but the client application does have APIs that are documented and available. So you can do it, it’s just not Web-service buzzword-compliant.

Is there an API to find out whether a feature is enabled, so you can disable / rearrange GUI? — Not in the current version.

The Road Ahead…

  • CRM integration
  • More activation scenarios and licensing models
  • More software asset management and BI analytics
  • Partnering with complementary code protection technologies
  • IDE integration

TechEd notes: 10 Ways To Improve Your Code

10 Ways To Improve Your Code
Neal Ford
Sr. Software Architect / Meme Wrangler
ThoughtWorks

Where did this topic come from?
Book: “The Productive Programmer”, Neal Ford
Exists in two parts, “mechanics” and “practices”.
Mechanics: how to speed you up, learning keyboard shortcuts.
Today is more Practical (and philosophical).

“The unexamined life is not worth living.” — Socrates

“Unexamined code isn’t worth executing.” — Neal, stealing from Socrates

1. Test driven design.

When you’re really rigorous at test-driven development, it has effects on your design. You’re creating the first consumer of your code.

  • Consumption awareness. You’re aware of how the rest of the world will use the code, before they use it.
  • Mocking of dependent objects. If you’re really unit testing, you’re mocking out the dependencies, which forces you to think about the collaboration between these objects.
  • Introverted vs. extroverted objects:
    • If you do TDD, you’ll learn to avoid “extroverted objects” that reach out to create other objects, fire constructors, allocate resources, etc.
    • Instead, you’ll use “introverted objects” where all dependencies are injected via parameters, properties, etc. You tend to move object creation to a few simple places, and can use things like real dependency injection. Also called “shy objects”.

2. Metrics and static analysis.

Compilation is a really, really weak form of unit testing. You can compile any sort of trash. “It compiles” doesn’t tell you much.

Source Monitor (can do many languages including C# and Delphi). Lots of metrics, including cyclomatic complexity. Can set thresholds and have it show the outliers. Has both GUI and command line. Costs you virtually nothing, and will help you find problem spots.

Cyclomatic complexity (1978): measure the complexity of your code. Has to do with the number of paths through the code, though it’s not quite that simple; it’s based on number of branches and decisions. But higher cyclomatic complexity tends to correlate to more bugs.

FxCop.

3. Good Citizenship.

Cooperation with the rest of the world.

Properties != Encapsulation.

  • See too many devs who use a tool to spit out public read/write properties for every one of their fields, and then engage their brain.
  • “Knee-jerk propertiation.”
  • Much better off passing values to a setter method like SetAddress, which means you can’t be a bad citizen by e.g. setting City without setting State — your object should go atomically from one good state to another good state.
  • Objects are the keepers of state, and they should guard that jealously.
  • Only create properties when you need to call them from real code.

Constructors

  • Specific contract for how to create valid objects.
  • How often is a valid object blank? (from a business standpoint) … Never!
  • Don’t provide default constructors for domain objects.
  • Push back on frameworks that try to require this
  • If you need a null object (and have a language that requires you to have a stateful object to say you have no state)…

Static methods

  • Should be a black box
  • You never worry, when you call the sqrt function, that the next time you call it it’s going to give you the cube root.
  • Statics should be non-stateful.
  • Where you get problems is when you mix statics with state.

Mixing static + state

  • The Evil Singleton Pattern
  • Bad because
    • Mixes responsibilities (doing stuff and maintaining its instance)
    • Untestable
    • Object version of global variables
  • Better: object and factory, where the factory handles the instantiation policing
    • Factory can even call object’s private constructor through reflection. Then you’re enforcing that nobody can instantiate the singleton accidentally.

4. YAGNI

Picture of gold-plated toilet

Discourage gold-plating.

  • Build simplest thing we need right now!
  • No speculative development. Speculative development:
    • Increases software entropy. The more code, the more complexity, even if you aren’t using it.
    • Only saves time if you can guarantee you won’t have to change it later
    • Leads to frameworks.
      • Frameworks are not inherently bad, but we have framework-itis.
      • Let’s face it, building a framework is cooler than what you should be doing right now.
      • Frameworks are written by people engaged in ivory-tower building.
      • The best frameworks are not created by somebody who wants to build a framework. The best are extracted from working code.

Changeability. Code with anticipatory design is larger and harder to refactor and maintain.

5. Shaving with Occam

Sir William of Occam: “Given multiple explanations, the simplest is best.”

Simplest is really hard to come by.

Dave Thomas was brought in to solve problem with volume of internal mail. Inter-office memos were constantly getting misrouted. So they brought in an OCR machine, and brought Dave in to write software for this thing. At one point, Dave said, “Couldn’t you solve this problem with colored envelopes?”

It’s really hard to understand the essence of the problem and address that.

We are drowning in complexity.

  • Essential complexity: We have a hard problem that we’re trying to solve.
  • Accidental complexity: We’ve made the problem hard.

The Goal

  • Simplify essential complexity
  • Kill accidental complexity

This also affects the kind of tools you use. E.g., “static” vs. “dynamic” languages. (I already noted this “ essence vs. ceremony“.) Something nasty and multithreaded would be better written in something like F#.

Interlude: the Top Ten Corporate Code Smells

  1. We invented our own web / persistence / messaging / caching / logging framework because none of the existing ones was good enough.
  2. We bought the entire tool suite (even though we only needed about 10% of it) because it was cheaper than buying the individual tools.
  3. We use BizTalk because… (I always stop listening at this point) Okay, it has some legitimate uses, but it’s been much abused.
  4. We can’t use any open source code because our lawyers say we can’t.
  5. We have an Architect (note the capital A) who reviews all code pre-checkin and decides whether or not to allow it into version control. (New feature in VSTS.)
  6. The only XmlDoc is the default message explaining how to change your default XmlDoc template.
  7. We keep all of our business logic in stored procedures… for performance reasons. There is some tortured logic at work here, but that ignores that dealing with stored procs will slow down your development. Let’s have a talk about premature optimization.
  8. We don’t have time to write unit tests — we’re spending too much time debugging.
  9. The initial estimate must be within 15% of the final cost, the post-analysis estimate must be within 10%, and the post-design estimate must be within 5%. (Punished for coming in too low as well as for coming in too high. The team will overestimate on purpose, get done early, not tell you about it, twiddle their thumbs until they hit the golden window, and then say, “Okay, all done!”)
  10. Blue Screen of Death.

Side note: Unless you work for NASA, your problem isn’t harder than everyone else’s. You’re just doing it wrong.

6. Question authority.

Dave Thomas’ story of angry monkeys. (The story of the stepladder, the bananas, and the ice water. “That’s the way we’ve always done it.”)

[Test]
public void UpdateCacheAndVerifyThatItemExists()

Long camel-cased names are hard to read, and test names tend to be long. Neal’s suggestion: use underscores just for test names.

[Test]
public void Update_cache_and_verify_that_item_exists()

Fluent interface:

ICar car = Car.describedAs()
              .Box
              .Insulated
              .Includes(Equipment.Ladder)
              .Has(Lining.Cork);

instead of setting lots of properties, to make it more readable for non-programmers. Thing is, it violates the rules of properties, by making a property getter (Box) that mutates the object. But in the context, it makes for much clearer code.

Killing I

  • Interfaces define semantic intent
  • No implementation details…
  • …except in the name!
  • Don’t name interfaces with a leading “I”
  • Name concrete classes with a naming pattern
  • (I’m not sure that I would agree with Neal on this, but it’s worth thinking about)

What’s Bad About Standards?

  • Forces you to create default constructors
  • Property setters return void
  • Can’t use PONOs for fluent interfaces

Non-intuitive

  • Pair programming (seems like it would be 50% slower, but in reality, once you settle into it, you develop 15% slower, but have 50% fewer defects)

Read AntiPatterns.

  • GiveMeEstimatesNow. Presented with a problem, asked for an estimate out of the blue; you don’t know anything about it, but the boss asks for a guess. That becomes an ironclad contract.
  • StandingOnTheShouldersOfMidgets. Have a disastrous tool or framework that you’re required to use in every application, because it’s a corporate standard.

Anti-patterns are the lore of software. Take advantage of this prior art. Don’t think that the problems at your job are uniquely yours.

7. Composed Method.

“Smalltalk Best Practice Patterns” by Kent Beck. Smalltalk people were some of the first OO programmers, and came up with elegant solutions. (They’ve got a head start on the rest of us.)

  • Every public method consists of steps implemented as private methods.
  • You can tell something’s wrong with the existing code if there have to be comments.
  • Extract methods.
  • Find opportunities for code reuse. Some of those methods you extract might start to look like Template Methods, which opens up more opportunities.

8. Polyglot Programming

Leveraging existing platforms with languages targeted at specific problems and applications

We have lots of .NET languages. Why not take advantage of them, rather than thinking there’s a framework for everything that you can use from the One True Language?

Looming problems / opportunities

  • Massively parallel processing (multithreading)
    • Use a functional language: F#, Haskell.net
  • Schedule pressure
    • Use a dynamic language: IronPython, IronRuby
    • Use an alternate Web framework: Django, Ruby on Rails
  • New approaches
    • Domain-specific languages (DSLs)
    • Fluent Interfaces

Write your multithreaded logic in F#, your GUI in C# or VB.NET, your unit tests in IronPython or IronRuby, and use DSLs

  • Wouldn’t that add complexity?
  • In the past, language == platform
  • Now, language != platform

Ola’s Pyramid

  • Stable language at the bottom, e.g. C#. Static-typed, statically-verified. Maybe even stricter than C#, like a mathematical language.
  • Above that, a dynamic (non-ceremonial, e.g. F#) language that lets you write code quickly.
  • Above that, a DSL that gets you closer to the problem domain.

9. Learn Every Nuance

  • Reflection
  • Regexes
  • Dependency injection
  • Closures
  • Lambda expressions
  • Extension classes
  • And once you’ve learned it, teach it to your co-workers. E.g., regular expressions.
  • Can save you orders of magnitude of work.

10. Anti-objects

Comes from OOPSLA paper called “Collaborative Diffusion”.

“The metaphor of objects can go too far by making us try to create objects that are too much inspired by the real world.”

Figure vs. ground. Sometimes you need to see the problem a different way.

Pac-Man console had less memory than a 10-year-old cell phone. Problem to solve for the ghosts: What is the shortest distance between two moving objects in a maze? Solution: don’t model the ghost; model the maze. Intelligence was built into the maze itself. Each cell had state. Invented “Pac-Man smell”. A cell he just moved off of had “maximum smell – 1”, and it decayed quickly. Ghosts just had to smell Pac-Man. The ghosts wander randomly until they pick up the scent, and then they move into the cell with higher smell. So they will never cut him off at the pass (on purpose)… but it was a very simple and memory-efficient solution.

TechEd 2008 notes: Why Software Sucks

This was a crowded, entertaining, fast-paced session. It’ll repeat later in the week, so if you’re reading this and you’re at TechEd, you should go see it.

Why Software Sucks
David S. Platt
Supreme and Exalted Dictator-For-Life
Rolling Thunder Computing, Inc

Some of this talk has been adapted from the book “Why Software Sucks… and What You Can Do About It” by David S Platt, Addison-Wesley

So, to start:

Users Think That Your Software Sucks.

Usually audiences will argue with that. It’s like alcoholics in denial. Word #1 in rule #1 of any twelve-step program is “Admit”.

Industries with the top number of complaints to the Better Business Bureau: #2. Internet Shopping Services. #5. Computers — Software & Service. #7. Internet Services. All in the software industry. Worse than used car dealers (#8) and collection agencies (#9). Only beat out by cell phone companies (#1), and they’re probably software problems too.

How did it get this way? Our audience has changed, and we haven’t adapted.

  • 1994 — about 2 million Web users
  • 2006 — about 1000 million Web users
  • And almost all of them use PCs for almost all Web access
  • The Web is now ubiquitous. Florida doesn’t even put their state name on the license plate — they put their Web address (myflorida.com) instead!

Platt’s First, Last, and Only Law of User Experience Design:

  • Know Thy User For He Is Not Thee
  • Engrave that on your heart with “Buy Low, Sell High” and “Always Cut the Cards”

Audience survey: What percentage of today’s attendees are female? In this room: less than 5%. Overall population is 52% female. User population used to be predominantly male, but not anymore.

Audience survey: What percentage of today’s attendees do NOT have a college degree (and aren’t currently working toward one)? In this room: one or two. User population used to be mainly college-educated, but today, 82% of population, 72% of US adults, don’t have a college degree.

Audience survey: What percentage of today’s attendees drive a car with a manual transmission? How many more WOULD if your spouses would let you buy one? Around 75% of people raised their hands. But in the general population, 12-14% of cars are sold with a manual transmission. Normal people don’t drive stick-shifts. They’re not interested in the driving process in and of itself. They don’t want to drive somewhere, they want to BE somewhere. Normal people don’t prize fine-grained control over ease of use.

Users don’t want to use your programs. They want to HAVE USED your programs. They want the benefit, not the process.

You don’t sell software. Your user does not come to you to buy software.

What is your customer actually buying? Let’s look at some non-software examples.

  • Lottery ticket: they’re not buying a lottery ticket, they’re buying futility. Well, okay, that’s true, but they think they’re buying a dream.
  • Toilet paper: They don’t buy it so they can admire the roll. They buy it because they want to use it for the designated purpose. Let’s just say they’re buying hygiene and leave it at that.
  • “The Sex-Starved Marriage” book: They’re really buying futility. Well, they think they’re buying sex and/or hope.
  • Insulin: They’re not buying needles and liquids. They’re buying life.

Still think you’re selling software? You’re not. You’re selling what software does.

Every single user says the exact same thing:

I just want it to work!

So: Make It Just Work. Sounds simple, but the laughs from the audience tell us all we need to know about why software sucks.

GOOD AND BAD EXAMPLES

  • Microsoft Word’s menu bar, floating free over the document. Has anyone ever done this because you wanted to? Have you seen anybody doing this because they wanted to? Heard of anyone?
    • Why did this happen? There was a programmer too geeky to get a date on Saturday night. So he went into the lab and took his frustration out on us!
    • No thought as to whether it would make the user more happy or less happy.
    • If you go to click on the menu and overshoot by a couple of pixels, you end up dragging it instead. Floating toolbars force us to be more precise. It forces the user to be more like a computer, and punishes you if you don’t.
  • Good example from Office: type hte and have it automatically change to The.
    • Understands and recognizes the humanity of the user.
    • Yes, I understand that humans are not diligent, thorough, precise. The computer will be those things for you. “I got your back.”
    • Enhances the humanity of the user. It’s as good as the previous one is bad, for the same reason.
  • www.google.com, in Sweden, comes up in Swedish.
    • Hmm, the user is a human being. Human beings like to be spoken to in their native language.
    • Take their best guess: you’re in Sweden, so you likely speak Swedish.
    • But there’s a “Google.com in English” link right there, which fixes it permanently (persistent cookie).
  • UPS tries the same thing, but doesn’t consider the user.
    • www.ups.com asks you to select your location, and doesn’t let you do anything until you do. You can’t track a package, order supplies, or send them an e-mail saying “Your site sucks, fix it.”
    • If you speak Swedish, you have to drop down the list, hit S, and hit down arrow twenty-six times, select it, then hit OK.
    • Compare to the post office. The clerk doesn’t tell you to click this button thirty times to tell him what language to talk to you in. He knows what country you’re in.
    • UPS didn’t put themselves in their users’ heads. They didn’t say, “How can we make this easy for our users?” Instead they said, “Let’s tell our users what to do.”
    • Amusing: You can type a UPS tracking number into Google, they’ll give you a link to track it, and one click takes you there. That means Google is a better UPS than UPS is.
  • Who has backed up their hard drive in the last week? (Ha.)
    • Like any human, we have a hierarchy of needs. Putting it off one more day probably won’t kill you today.
    • PC Editor’s Choice Backup Manager. (Genie Backup Manager Home Edition 7.0)
    • First choice: Normal or Easy?
    • So… Easy is the opposite of Normal… and Not Easy is the default?
    • Treeview with checkboxes… immensely powerful and flexible, but when was the last time you wanted to back up anything other than everything?
    • Backup type: Normal, Increment (so Increment isn’t Normal?), or Mirror (which is neither Increment or Normal, and what the heck is it, anyway)?
    • You do not want to back up your hard drive. You want to have backed up your hard drive.
    • Carbonite (Internet backup) has a picture of a guy in a hammock. Very few choices. Choices are “My Documents”, “Everything”, and “Pick and Choose”. Nobody has ever selected “Pick and Choose”. It’s there because the programmers insisted.

CONVINCING THE BOSS

How do we convince the boss that our apps need to Just Work?

MAKING IT JUST WORK

Plattski’s Handful

  • Add a Virgin to the Design Team
    • Somebody who doesn’t know the internal workings of the problem
    • “The text in the Untitled file has changed. Do you want to save the changes?”
    • Exposing internal workings directly to the user; forcing user to learn and understand how the program is written internally. User shouldn’t have to know about dirty buffers.
    • “Blindness improves your vision” — Po Bronson
    • Put a virgin on your team, and don’t shout them down — listen to them.
  • Break Convention When Needed
    • MS Money doesn’t ask when to save to disk. It just works.
  • Don’t Let Edge Cases Complicate the Mainstream
    • A theorem that’s true 99 times out of 100 is a false theorem.
    • A program that makes 99 out of 100 users happy is doing pretty darn good.
    • The Starbucks store finder asks you for a search radius. Very few people ask, “How many Starbucks are there within five miles?” They ask, “Where’s the nearest Starbucks?” The one guy who does care dictated the user experience for everybody else.
  • Instrument — Carefully
    • Track what the users are doing, and analyze it
    • Ultimate way of Knowing Thy User
    • Microsoft has this, but they won’t license it out, so everyone else has to write their own
    • knowthyuser.com — David is working on a framework for this
  • Always ask: Is This Individual Design Decision Taking Us Closer to Just Working, or Farther Away?
    • Sum of many, many small decisions

Make software not suck. Make it Just Work.

TechEd 2008 overheard: Historical debugger

On the escalator, I overheard someone telling his colleague about an upcoming feature, the Visual Studio Historical Debugger.

It’ll let you step backward in time. Program threw an exception? You don’t have to just look at where it stopped; you’ll actually be able to step backward to find out how the program got into that state.

I asked the guy about it, and he said it’ll be in the next version of Visual Studio, code-named Rosario. Since I only overheard part of a conversation, and didn’t actually attend the session where he’d seen the demo, that’s about all I know, so don’t ask me for details or release dates. I assume you’ll have to tell it when to start and stop recording, but that’s just an educated guess. The above link has a tiny bit more info and a couple of screenshots.

This isn’t a new idea; there’s been an “omniscient debugger” for Java for at least a year. But it’ll be pretty awesome to have it available for a language I use.

So… any chance of Delphi ever getting this? (grin)