Joe White’s Blog

Life, .NET, and Cats


TechEd 2008 notes: Managed Add-In Framework

Wednesday, June 4th, 2008

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

Wednesday, June 4th, 2008

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 0×0, 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

Wednesday, June 4th, 2008

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

Wednesday, June 4th, 2008

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

Tuesday, June 3rd, 2008

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

Tuesday, June 3rd, 2008

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

Tuesday, June 3rd, 2008

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

Tuesday, June 3rd, 2008

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)

TechEd 2008 notes: “Design Patterns” in Dynamic Languages

Tuesday, June 3rd, 2008

These notes are probably fairly coherent. They’re definitely worth the read if you’re interested in design patterns and know something about Ruby, although I don’t know whether my notes would stand up very well if you don’t already know Ruby.

“Design Patterns” in Dynamic Languages
Neal Ford
Software Architect / Meme Wrangler
ThoughtWorks

Pattern solutions from weaker languages have more elegant solutions in dynamic languages

Ruby on Rails is running on IronRuby (as of RailsConf last week)

“Design Patterns: Making C++ Suck Less” by GoF

  • Really good for two things
    • Good definition for common kinds of problems we encounter
    • Insomnia cure
  • Examples in C++ and Smalltalk
  • People mistakenly thought it was a recipe book

Patterns define common problems. Dynamic languages give you better tools to solve those problems.

Not “static vs. dynamic”. It’s “ceremony vs. essence”. Statically-typed languages like C# require a lot of ceremony to get things done; long distance between intent and result. Dynamic languages have less distance.

ITERATOR

Side note: Neal isn’t a big fan of UML, because it’s not technical enough for technical people, and too technical for non-technical people. This is the only talk where you’ll ever see him use UML.

Provide way to access elements of an aggregate sequentially without exposing the details.

container.each {|i| puts i}

Built-in iterator: each. Can also make an iterator object. C# has very similar things: IEnumerable/IEnumerator and foreach

COMMAND

Encapsulates a request as an object.

commands = []
(1..10).each do |i|
  commands << proc { count += i }
end

Any language with closures already has Command built-in. There’s a trend here: languages are adding built-in patterns. C# has this too.

But: Command pattern may also support undoable operations.

class Command
  def initialize(do_proc, undo_proc)

Dynamic languages don’t preclude structure, but they let you delay it until necessary.

See blog post / rant: “Execution in the Kingdom of Nouns“. Command was essentially designed to give you a way to pass verbs around.

BUILDER

Separate construction process so the same process can create different representations.

Dynamicize with ad hoc combinations: method_missing. So instead of calling several methods in a row to set up different features, you can do things like parsing the method name: add_cd_and_dvd_and_turbo (”And” is a “bubble word” in DSL terms: it’s there for readability only.)

Used by Rails for find methods: find_by_column1_and_column2_…

INTERPRETER

Given a language, define a grammar and interpreter. (Tough to use as a recipe!)

Admission that the language you’re writing your app in isn’t expressive enough to get the job done.

Greenspun’s Tenth Rule:

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

GoF book assumes you’re writing a parser, but an increasingly common solution is an internal DSL (e.g. LINQ).

recipe = Recipe.new "Spicy bread"
recipe.add 200.grams.of "Flour"
recipe.add 1.lb.of "Nutmeg"

Need to be able to add methods to numbers. No problem. Open class. More flexible than extension methods in C#, because you can change or remove methods.

class Numeric
  def gram
    self
  end
  alias_method :grams, :gram
  def pound
    self * 453.59237
  end
  alias_method :pounds, :pound
  alias_method :lb, :pound
  alias_method :lbs, :pound
  def of ingredient
    if ingredient.kind_of? String
      ingredient = Ingredient.new(ingredient)
    end
    ingredient.quantity = self
    ingredient
  end
end

Side note: I might have done of by making a to_ingredient method on both String and Ingredient, and call that. Wonder if that would actually be better or not, though it would avoid the kind_of? call.

Semi-external DSL:

ingredient "flour" has Protein=11.5, Lipid=1.45, Sugars=1.12, Calcium=20, Sodium=0

Do a couple of substitutions to change that into a legal line of Ruby code, and then do instance_eval.

Internal DSL == embedded interpreter. Meets the intent of the GoF interpreter pattern better than lex/yacc, especially since it’s less prohibitive. Ruby on Rails is essentially a collection of internal DSLs.

FACTORY

Define interface for creating an object; let subclasses decide which class to instantiate.

Trivial in Ruby:

def create_from_factory(factory)
  factory.new
end

DECORATOR

Attach additional responsibilities dynamically. Flexible alternative to subclassing.

module Decorator
  def initialize(decorated)
    @decorated = decorated
  end
  def method_missing(method, *args)
    args.empty? ?
      @decorated.send(method) :
      @decorated.send(method, args)
  end
end

Whip.new(Coffee.new).cost

Or, make the decorations modules:

module Whipped
  def cost
    super + 0.2
  end
end

x = Coffee.new
x.extend Sprinkles
x.extend Whipped

Or make it even nicer:

Coffee.with Sprinkles, Whip

RECORDER

class Recorder
  def initialize
    @messages = []
  end
  def method_missing(method, *args, &block)
    @messages << [method, args, block]
  end
  def play_back_to(obj)
    @messages.each do |method, args, block|
      obj.send(method, *args, &block)
    end
  end
end

Interesting nuance: what about methods that are already defined on Recorder, e.g. to_s? Anticipated in Ruby 1.8: there’s a class called BlankSlate.

ADAPTER

Convert one interface to another. Round hole / square peg.

class SquarePegAdapter
  def radius
    Math.sqrt(((@peg.width / 2) ** 2) * 2)

That’s the traditional adapter: a wrapper. But in Ruby, you could solve it a different way:

class SquarePeg
  def radius
    Math.sqrt(((width / 2) ** 2) * 2)
  end
end

Can also add methods to a single instance instead of the entire class.

What if SquarePeg already had a radius method?

class SquarePeg
  include InterfaceSwitching
  def width
    @width
  end
  def_interface :normal, :width

  def width
    @width / 3
  end
  def_interface :holes, :width

  def initialize(width)
    set_interface :normal
    @width = width
  end
end

Then you can use a with_interface method to adapt the class to a particular interface, yield self, then put itself back. Short-lived adapter.

DYNAMIC LANGUAGE PATTERNS

ARIDIFIER

Pragmatic Programmer: “Don’t Repeat Yourself.”

Ceremonious languages create floods. They create repetition you don’t even see because you’re so used to it. Essence languages allow aridification.

class Grade
  class << self
    def for_score_of(grade)
      case grade
        when 90..100: 'A'
        when 80..90 : 'B'
        when 70..80 : 'C'
        when 60..70 : 'D'
        when Integer: 'F'
        when /['A-D]/, /[F]/ : grade
        else raise "Not a grade: #{grade{"
      end
    end
  end
end

def test_numerical_grades
  for g in 90..100
    assert_equal "A", Grade.for_score_of(g)
  end
  for g in 80..90
    assert_equal "B", Grade.for_score_of(g)
  end

Lots of repetition. Better:

TestCrades.class_eval do
  grade_range = {
    'A' => 90..100,
    ...

  grade_range.each do |k, v|
    method_name = ("test_" + k + "_letter_grade").to_sym
    define_method method_name do
      ...

No duplication. You write the loop once, inside that call to define_method.

STATE

Door with states: Open and Closed. Model the states as mixins, and extend them. Problem: old methods don’t go away.

Solution: Mixology Ruby gem that adds unmix and mixin methods.

Dynamic languages use language facilities to create simpler solution. GoF solutions are all structural; that’s why they all have UML diagrams: the way to solve problems is to add structure. You can still do that in dynamic languages, but often don’t need to.

Understand patterns for what they are: descriptions of common problems. Don’t get caught up in implementation details. Implement solutions that are more elegant and take advantage of your tools.

“Simplexity”: taking complicated code and move it to another place; may add more complexity somewhere else, but simplifies other code. Languages with strong metaprogramming.

Q&A

Which of these patterns are implementable in IronRuby? — They’re running IronRuby against the Ruby language specs. Virtually all of these should run now.

Looks like cleverness for cleverness’ sake. — Compare to AOP or LINQ. Not everyone on your team has to understand how it works internally. But don’t go hog-wild with this stuff. Metaprogramming was 3.5 - 5% of his team’s Ruby code. Use metaprogramming surgically, not as a sledgehammer.

Some programmers don’t understand e.g. C++ templates. Is metaprogramming the same kind of problem? — No, because in C++, templates are in your face all the time; the complexity is hard to hide. In Ruby, it just looks like you’re adding keywords to the language.

Why not just write your own language on the DLR? — Some people probably will, but writing a good, expressive language is really hard, way harder than making a good framework.

At a company that doesn’t use any dynamic languages, how to decide which one to use? — Start using one to do something you already need to do; you’ll get a flavor for how it feels and how its concepts map to your view of the world. Start with infrastructure stuff. Start using rake, or writing tests with IronRuby, or do scripting.

Aren’t these languages dangerous because you don’t have static typing? — Yes. But: a compiler is a good verifier, but only for a very small surface area. Unit testing, with dynamic languages, is not optional. (Arguably, it’s not optional with static languages either.)

Can you create unit tests that cover all possible scenarios? — Sure. They go for 100% code coverage.

Does he know whether RSpec works in IronRuby? — Doesn’t know, but if Rails works, RSpec likely does.

TechEd 2008 notes: Bill Gates’ keynote

Tuesday, June 3rd, 2008

Bill Gates keynote

This is Bill’s last public appearance as a full-time Microsoft employee.

Video: Bill Gates’ Last Full Day

Technology Megatrends

  • Hardware performance: Moore’s Law, multi-core
  • Ubiquitous broadband, RPC
  • Unlimited storage
  • Mobility & new devices
  • Natural user interface: touch screen, speech recognition
  • High fidelity displays

Opportunities for Developers

  • Presentation
  • Business Logic
  • Data
  • Services

PRESENTATION

Silverlight demo (S. Somasegar)

  • Crossfader: social networking media sharing site
  • Silverlight is a true subset of WPF, so Silverlight controls can be reused in WPF
  • Silverlight 2 Beta 2 should be delivered by the end of this week, with a Go-Live license

BUSINESS LOGIC

Modeling demo (Brian Harry)

  • View > Architecture Explorer: class diagram (design as it actually is)
  • Architecture Layer diagram (design as it was meant to be: diagram of layers; can be validated against actual code by right-clicking in designer; can be a check-in policy)
  • Upcoming release of VSTS for Database Professionals: can maintain DB2 databases from Visual Studio
  • Database refactorings: rename field in database, renames in code (available today)
  • Codename “Oslo”: modeling tools, modeling language, model repository

DATA

SQL Server 2008 demo (Dave Campbell)

  • Spatial data
  • File integration: VARBINARY has an attribute saying “store it as a file stream”; still gets backed up
  • Full timezone support: can store timestamps along with the timezone
  • Available in the next month or two

SERVICES

FUTURE OF APPLICATION DEVELOPMENT

  • Design
    • Analysis & design tools
    • Next generation declarative languages
  • Execution
    • Process aware engines/platforms
    • Self-aware system management

Microsoft Robotics demo (Tandy Trower)

  • Robotics are expensive and require specialty maintainers
  • Just emerging at the personal level — about where PCs were in the early 1980s
  • Microsoft Robotics Developer Studio: development for robots, including simulation
  • Self-balancing robot with dextrous arms and a picture of Steve Ballmer’s face
  • RoboChamps competition: program simulated robots, win real robots (www.robochamps.com)

Joe White's Blog copyright © 2004-2008. Portions of the site layout use Yahoo! YUI Reset, Fonts, and Grids.
Proudly powered by WordPress. Entries (RSS) and Comments (RSS).