Showing posts with label twelve-days-of-code. Show all posts
Showing posts with label twelve-days-of-code. Show all posts

Saturday, December 21, 2013

Guess what I’ll doing during Christmas break?

It arrived at work just before my Christmas vacation…

WP_20131219_003

It came with stickers…

WP_20131219_005

Expect a few more posts from me over the Christmas break about the new Kinect for Windows.

By the way, there’s still time for you to get in on this as Microsoft has extended the Developer Preview for another 500 devices.

Monday, February 08, 2010

Twelve Days of Code – Wrap up

Well it’s been a very long twelve days indeed, and I accomplished more than I thought I would.  But alas, all good things must come to end, so after a short hiatus on the blog I’m back to close out the Twelve Days of Code series for 2009.

For your convenience, here’s a list of the posts:

I want to thank all those who showed interest in the concept and if there are folks out there who were following along at home, please drop me a line or a comment.

For those interested in seeing some of the .NET 4.0 code and extending my work, the code is available for download.

I may pick up the experiment again once the next release candidate for Visual Studio is released.

submit to reddit

Thursday, January 07, 2010

Twelve Days of Code – Unity Framework

As part of the twelve days of code, I’m building a Pomodoro style task tracking application and blogging about it. This post is the seventh in this series. This post focuses on using the Microsoft Unity Framework in our .NET 4.0 application.

This post assumes assumes that you are familiar with the last few posts and have a working understanding of Inversion of Control.  If you’re new to this series, please check out some of the previous posts and then come back.  If you’ve never worked with Inversion of Control, it’s primarily about decoupling objects from their implementation (Factory Pattern, Dependency Injection, Service Locator) – but the best place to start is probably here.

Overview

Our goal for this post is to remove as many hard-code references to types as possible.  Currently, the constructor of our MainWindow initializes all the dependencies of the Model and then manually sets the DataContext.  We need to pull this out of the constructor and decouple the binding from TaskApplicationViewModel to ITaskApplication.

Initializing the Container

We’ll introduce our inversion of control container in the Application’s OnStartup event.  The container’s job is to provide type location and object lifetime management for our objects, so all the hard-coded initialization logic in the MainWindow constructor is registered here.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        IUnityContainer container = new UnityContainer();
        
        container.RegisterType<ITaskApplication, TaskApplicationViewModel>();
        container.RegisterType<ITaskSessionController, TaskSessionController>();
        container.RegisterType<IAlarmController, TaskAlarmController>();
        container.RegisterType<ISessionRepository, TaskSessionRepository>();

        Window window = new MainWindow();
        window.DataContext = container.Resolve<ITaskApplication>();
        window.Show();

        
        base.OnStartup(e);
    }
}

Also note, we’re initializing the MainWindow with our data context and then displaying the window.  This small change means that we must remove the MainWindow.xaml reference in the App.xaml (otherwise we’ll launch two windows).

Next Steps

Aside from the simplified object construction, it would appear that the above code doesn’t buy us much: we have roughly the same number of lines of code and we are simply delegating objection construction to Unity.  Alternatively, we could move the hard-coded registrations to a configuration file (though that’s not my preference here).

In the next post, we’ll see how using Prism’s Bootstrapper and Module configuration allows us to move this logic into their own modules.

In the next step, we’ll look at using P

submit to reddit

Saturday, January 02, 2010

Twelve Days of Code – Entity Framework 4.0

As part of the twelve days of code, I’m building a Pomodoro style task tracking application and blogging about it. This post is the sixth in this series. Today I’ll be adding some persistence logic to the Pomodoro application.

I should point I’ve never been a huge fan of object-relational mapping tools, and while I’ve done a few tours with SQL Server I haven’t played much with SQLite.  I’ve heard good things about the upcoming version of the Entity Framework in .NET 4.0, so this post gives me a chance to play with both.

Getting Ready

As SQLite isn’t one of the default providers supported by Visual Studio 2010 (Beta 2), I downloaded and installed SQLite.  The installation adds the SQLite libraries to the Global Assembly Cache, and adds Designer Support for connecting to a SQLite database through the Server Explorer.  The installation and GAC’d assemblies may prove to be an issue later when we want to deploy the application, but we’ll worry about that later.

Creating a Session Repository

So far, the project structure has a “Core” and “Shell” project where the “Core” project contains the central interfaces for the application.  Since the ITaskSessionController already has the responsibility of handling starting and stopping of sessions, it is the ideal candidate to interact with a ISessionRepository for recording these activities against a persistent store.

To handle auditing of sessions, I created a ISessionRepository interface which lives in the Core library:

interface ISessionRepository
{
    void RecordCompletion(ITaskSession session);
    void RecordCancellation(ITaskSession session);
}

Although we don't have an implementation for this interface, we do know how that an object with this signature will be used by the TaskSessionController.  In anticipation of these changes, we add tests to the TaskSessionController that verify it communicates with its dependency:

public TaskSessionControllerSpecs : SpecFor<TaskSessionController>
{
  // ... initial context setup with Mock ISessionRepository
  // omitted for clarity

  public class when_a_session_completes : TaskSessionControllerSpecs
  {
     // omitted for clarity

     [TestMethod]
     public void ensure_activity_is_recorded_in_repository()
     {
         repositoryMock.Verify( 
            r => r.RecordCompletion(
                    It.Is<ITaskSession>( (s) => s == session )
                        );
     }
  }
}

To ensure the tests pass, we extend the TaskSessionController to take a ISessionRepository in its constructor and add the appropriate implementation.  Naturally, because the constructor of the TaskSessionController has changed, we adjust the fixture setup so that the code will compile.  Below is a snippet of modified TaskSessionController:

public class TaskSessionController : ITaskSessionController
{
    public TaskSessionController(ISessionRepository repository)
    {
        SessionRepository = repository;
    }

    protected ISessionRepository SessionRepository
    {
        get; set;
    }

    public void Finish(ITaskSession session)
    {
        session.Stop()

        SessionRepository.RecordCompletion(session);
    }

    // ...omitted for clarity
}

Adding ADO.NET Entity Framework to the Project

While we could add the implementation of the ISessionRepository into the Core library, I’m going to add a new library Pomodoro.Data where we’ll add the Entity Framework model.  This strategy allows us to extend the Core model and provides us with some freedom to create alternate persistence strategies simply by swapping out the Pomodoro.Data assembly.

Once the project is created, we add the Entity Framework to the project using the Add New “ADO.NET Entity Data Model” and follow the wizard:

Pomodoro.Data

Note, that the wizard adds the appropriate references to the project automatically. 

Since we don’t have a working database, we’ll choose to create an Empty Model.  Later on, we’ll generate the database from our defined model.

empty-model 

Creating a Data Model

One of the new features of the Entity Framework 4.0 is that it allows you to bind to an existing data model.  Although the TaskSession could be considered as a candidate for an existing model, it doesn’t fit the bill cleanly – Sessions represent countdown timers and they don’t track the final outcome.  Instead, we’ll use the default behavior of the framework and manually generate a model class, TaskSessionRecord:

add-new-entity

For our auditing purposes, we only need to record an ID, Start and End Times and whether the session was completed or cancelled.

task-session-record

Creating the Database from the Model

After the model is complete, we generate the database from the model:

  1. Right click the designer and choose “Model Browser”
  2. In the Data Store, choose “Generate Database from Model”
  3. Create a new database connection.  In our case, we specify SQLite provider
  4. Finish our the wizard by clicking Next and Finish.

new-database-connection

The wizard produces the Database and the matching DDL file to generate the tables.  Note that SQLite must be installed in order to have it appear as an option in the wizard.

Unfortunately, I wasn’t able to create the SQLite database using any of the tools with Visual Studio.  Instead, I cheated and manually created the TaskSessionRecord table.  We’ll hang onto the generated ddl file because we may want to programmatically generate the database at some point.  For the time being, I’ll cheat and copy the database to the bin\Debug folder.

Implementing the Repository

The repository implementation is fairly straightforward.  We simply instantiate the object context (we specified part of the name when we added the ADO.NET Entity Data Model to the project), add a new TaskSessionRecord to the EntitySet and then save the changes to commit the transaction:

namespace Pomodoro.Data
{
    public class TaskSessionRepository : ISessionRepository
    {
        public void RecordCompletion(ITaskSession session)
        {
            using (var context = new PomodoroDataContainer())
            {
                context.TaskSessionRecords.AddObject(new TaskSessionRecord(session, true));
                context.SaveChanges();
            }
        }

        public void RecordCancellation(ITaskSession session)
        {
            using (var context = new PomodoroDataContainer())
            {
                context.TaskSessionRecords.AddObject(new TaskSessionRecord(session, false));
                context.SaveChanges();
            }
        }
    }
}

Note that to simplify the code, I extended the auto generated TaskSessionRecord class to provide a convenience constructor.  Since the auto generated class is marked as partial, the convenience constructor is placed in its own file.  As some of the existing generated code requires the presence of an empty constructor (which is implicitly defined by the compiler if not present), we must also include a default constructor.

public partial class TaskSessionRecord
{
    // needed to satisfy some of the existing generated code
    public TaskSessionRecord()
    {
    }

    public TaskSessionRecord(ITaskSession session, bool complete)
    {
        Id = session.Id;
        StartTime = session.StartTime;
        EndTime = session.EndTime;
        Complete = complete;
    }
}

Integrating into the Shell

To integrate the new SessionRepository into the Pomodoro application we need to add the database, Pomodoro.Data assembly and the appropriate configuration settings.  For the time being, we’ll add a reference to Pomodoro.Data library to the Shell application – this strategy may change if we introduce a composite application pattern such as Prism or MEF.  For brevity sake, I’ll manually copy the database into the bin\Debug folder.

The connection string settings appear in the app.config like so:

<connectionStrings>
  <-- formatted for readibiliy -->
  <add name="PomodoroDataContainer" 
       connectionString="metadata=res://*/PomodoroData.csdl|res://*/PomodoroData.ssdl|res://*/PomodoroData.msl;
                    provider=System.Data.SQLite;
                    provider connection string=&quot;data source=Pomodoro.sqlite&quot;" 
       providerName="System.Data.EntityClient" />
</connectionStrings>

One Last Gotcha

As the solution is compiled against .NET Framework 4.0 and our Sqlite assemblies are compiled against .NET 2.0, we receive a really nasty error when the System.Data.SQLite assembly loads into the AppDomain:

Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information

We solve this problem by adding useLegacyV2RuntimeActivationPolicy="true" to the app.config:

<startup useLegacyV2RuntimeActivationPolicy="true">
  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>

Next Steps

In the next post, we’ll look at adding Unity as a dependency injection container to the application.

submit to reddit

Thursday, December 31, 2009

Twelve Days of Code – Windows 7 Shell Integration

As part of the twelve days of code, I’m building a Pomodoro style task tracking application and blogging about it. This post is the fifth in this series.  Today I’ll cover adding some of the cool new Windows 7 Shell integration features in WPF 4.0.

I’ll be revisiting some of the xaml and object model for this post, so it wouldn’t hurt to read up:

WPF 4.0 offers some nice Windows 7 Shell integration that are easy to add to your application.

Progress State

Since the Pomdoro application’s primary function is to provide a countdown timer, it’s seems like a natural fit to use the built-in Windows 7 Taskbar progress indicator to show the time remaining.  Hooking it up was a snap.  The progress indicator uses two values ProgressState and ProgressValue, where ProgressState indicates the progress mode (Error, Indeterminate, None, Normal, Paused) and ProgressValue is a numeric value between 0 and 1.  Two simple converters provide the translation between ViewModel and View, one to control ProgressState and the other to compute ProgressValue.

<Window.TaskbarItemInfo>
    <TaskbarItemInfo
        ProgressState="{Binding ActiveItem, Converter={StaticResource ProgressStateConverter}}"
        ProgressValue="{Binding ActiveItem, Converter={StaticResource ProgressValueConverter}}"
        >
    </TaskbarItemInfo>
</Window.TaskbarItemInfo>

Which looks something like this:

taskbar-progress

Note that for ProgressValue I’m binding to ActiveItem instead of TimeRemaining.  This is because the progress value is obtained through a percent complete calculation -- time remaining in the original session length – which requires that both values are available to the converter.  I suppose this could have been calculated through a multi-binding, but the single converter makes things much easier.

namespace Pomodoro.Shell.Converters
{
    [ValueConversion(typeof(ITaskSession), typeof(System.Windows.Shell.TaskbarItemProgressState))]
    public class ProgressStateConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && value is ITaskSession)
            {
                ITaskSession session = (ITaskSession)value;

                if (session.IsActive)
                {
                    return TaskbarItemProgressState.Normal;
                }
            }
            return TaskbarItemProgressState.None;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }


    [ValueConversion(typeof(ITaskSession), typeof(double))]
    public class ProgressValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && value is ITaskSession)
            {
                ITaskSession session = (ITaskSession)value;

                if (session.IsActive)
                {
                    int delta = session.SessionLength - session.TimeRemaining;
                    
                    return (double)(delta / (double)session.SessionLength);
                }
            }
            return 1;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

This is all well and good, but there’s a minor setback: Progress will not increment unless the PropertyChanged event is raised for the ActiveItem property.  This is an easy fix: the ITaskSession needs to expose a NotifyProgress event and the ITaskApplication needs to notify the View when the event fires.  Since the progress indicator in the taskbar is only a few dozen pixels wide, spamming the View with each millisecond update is a bit much.  We solve this problem by throttling the amount the event is raised using a NotifyInterval property.

// from TaskSessionViewModel
void OnTimer(object sender, ElapsedEventArgs e)
{
    NotifyProperty("TimeRemaining");

    if (IsActive)
    {
        // if notify interval is set
        if (NotifyInterval > 0)
        {
            notifyIntervalCounter += TimerInterval;

            if (notifyIntervalCounter >= NotifyInterval)
            {
                if (NotifyProgress != null)
                {
                    NotifyProgress(this, EventArgs.Empty);
                }
                notifyIntervalCounter = 0;
            }
        }
    }

    if (TimeRemaining == 0)
    {
        // end timer
        IsActive = false;

        if (SessionFinished != null)
        {
            SessionFinished(this, EventArgs.Empty);
        }
    }
}

TaskbarInfo Buttons

Using the exact same command bindings mentioned in my last post, adding buttons to control the countdown timer from the AreoPeek window is dirt simple. The only gotcha is that the taskbar buttons do not support custom content, instead you must specify an image to display anything meaningful to the user.

<Window ....>

    <Window.Resources>
        <!-- play icon for taskbar button -->
        <DrawingImage x:Key="PlayImage">
            <DrawingImage.Drawing>
                <DrawingGroup>
                    <DrawingGroup.Children>
                        <GeometryDrawing Brush="Black" Geometry="F1 M 50,25L 0,0L 0,50L 50,25 Z "/>
                    </DrawingGroup.Children>
                </DrawingGroup>
            </DrawingImage.Drawing>
        </DrawingImage>

        <!-- stop icon for taskbar button -->
        <DrawingImage x:Key="StopImage">
            <DrawingImage.Drawing>
                <DrawingGroup>
                    <DrawingGroup.Children>
                        <GeometryDrawing Brush="Black" Geometry="F1 M 0,0L 50,0L 50,50L 0,50L 0,0 Z "/>
                    </DrawingGroup.Children>
                </DrawingGroup>
            </DrawingImage.Drawing>
        </DrawingImage>

        // ... converters
        
    </Window.Resources>

    <Window.TaskbarItemInfo>
        <TaskbarItemInfo ... >
            
            <TaskbarItemInfo.ThumbButtonInfos>
                <ThumbButtonInfoCollection>

                    <!-- start button -->
                    <ThumbButtonInfo
                        ImageSource="{StaticResource ResourceKey=PlayImage}"
                        Command="{Binding StartCommand}"
                        CommandParameter="{Binding ActiveItem}"
                        Visibility="{Binding ActiveItem.IsActive, 
                                     Converter={StaticResource BoolToHiddenConverter}, 
                                     FallbackValue={x:Static Member=pc:Visibility.Visible}}"
                        />

                    <!-- stop button -->
                    <ThumbButtonInfo
                        ImageSource="{StaticResource ResourceKey=StopImage}"
                        Command="{Binding CancelCommand}"
                        CommandParameter="{Binding ActiveItem}"
                        Visibility="{Binding ActiveItem.IsActive, 
                                     Converter={StaticResource BoolToVisibleConverter}, 
                                     FallbackValue={x:Static Member=pc:Visibility.Collapsed}}"
                        />
                </ThumbButtonInfoCollection>
            </TaskbarItemInfo.ThumbButtonInfos>
        </TaskbarItemInfo>
    </Window.TaskbarItemInfo>

    // ....

</Window>

The applied XAML looks like this:

taskbar-buttons

Next Steps

The next post we’ll add some auditing capability to the pomodoro application using SQLite and the Entity Framework version in .NET 4.0.

submit to reddit

Tuesday, December 29, 2009

Twelve Days of Code – Views

As part of the twelve days of code, I’m building a Pomodoro style task tracking application and blogging about it. This post is the fourth in this series -- we’ll look at some basic XAML for the View, data binding and some simple styling.

Some basic Layout

Our Pomodoro application doesn’t require a sophisticated layout with complex XAML.  All we really need is an area for our count down timer, and two buttons to start and cancel the Pomodoro.  That being said, we’ll drop a textbox and two buttons into a grid, like so:

<Window x:Class="Pomodoro.Shell.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Pomodoro" Width="250" Height="120">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        
        <!-- active item -->
        <TextBlock Grid.Column="0"/>
        
        <!-- command buttons -->
        <StackPanel Orientation="Horizontal" Grid.Column="1">
            <Button Content="Start" />
            <Button Content="Stop" />
        </StackPanel>
        
    </Grid>
</Window>

Which looks something likes this:

Basic Pomodo - Yuck!

Binding to the ViewModel

The great thing behind the Model-View-ViewModel pattern is that we don’t need goofy “code-behind” logic to control the View.  Instead, we use WPF’s powerful data binding to graph the View to the ViewModel. 

There are many different ways to bind the ViewModel to the View, but here’s a quick and dirty mechanism until there’s a inversion of control container to resolve the ViewModel:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var sessionController = new TaskSessionController();
        var alarmController = new TaskAlarmController();

        var ctx = new TaskApplicationViewModel(sessionController, alarmController);
        this.DataContext = ctx;
    }
}

The XAML binds to the TaskApplicationViewModel’s ActiveItem, StartCommand and CancelCommands:

<!-- active item -->
<TextBlock Text="{Binding ActiveItem.TimeRemaining}" />

<!-- command buttons -->
<StackPanel Orientation="Horizontal" Grid.Column="1">
    <Button Content="Start" 
            Command="{Binding StartCommand}" 
            CommandParameter="{Binding ActiveItem}"                 
            />
    <Button Content="Stop" 
            Command="{Binding CancelCommand}" 
            CommandParameter="{Binding ActiveItem}"
            />
</StackPanel>

The Count Down Timer

At this point, clicking on the Start button shows the pomodoro counting down in milliseconds.  I had considered breaking the count down timer into its own user control, but chose to be pragmatic and use a simple TextBlock.  The display can be dressed up using a simple converter:

namespace Pomodoro.Shell.Converters
{
    [ValueConversion(typeof(int), typeof(string))]
    public class TimeRemainingConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is int)
            {
                int remaining = (int)value;

                TimeSpan span = TimeSpan.FromMilliseconds(remaining);

                return String.Format("{0:00}:{1:00}", span.Minutes, span.Seconds);
            }
            return String.Empty;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Control Button Visibility

With the data binding so far, the Pomodoro application comes to life with a crude but functional user-interface.  To improve the experience, I’d like to make the buttons contextual so that only the appropriate button is shown based on the state of the session.  To achieve this effect, we bind to the IsActive property to control visibility state with mutually exclusive converters: BooleanToVisibleConverter and BooleanToCollapsedConverter.  I honestly don’t know why these converters aren’t part of the framework as I use this concept frequently. 

namespace Pomodoro.Shell.Converters
{
    [ValueConversion(typeof(bool), typeof(Visibility))]
    public class BooleanToHiddenConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is bool)
            {
                bool hidden = (bool)value;
                if (hidden)
                {
                    return Visibility.Collapsed;
                }
            }
            return Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    [ValueConversion(typeof(bool),typeof(Visibility))]
    public class BooleanToVisibleConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is bool)
            {
                bool active = (bool)value;

                if (active)
                {
                    return Visibility.Visible;
                }
            }
            return Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

However, there’s a Binding problem with all of these converters: by default, the ActiveItem of the TaskApplication is null and none of the bindings will take effect until after the object has been set.  This is easily fixed with a FallbackValue in the binding syntax:

<Window ...
        xmlns:local="clr-namespace:Pomodoro.Shell.Converters"
        xmlns:pc="clr-namespace:System.Windows;assembly=PresentationCore">

    <Window.Resources>
        <local:BooleanToVisibleConverter x:Key="BoolToVisibleConverter" />
        <local:BooleanToHiddenConverter x:Key="BoolToHiddenConverter" />
        <local:TimeRemainingConverter x:Key="TimeSpanConverter" />
    </Window.Resources>

    <Grid>

        <!-- active item -->
        <TextBlock Text="{Binding ActiveItem.TimeRemaining, Converter={StaticResource TimeSpanConverter}, 
                                  FallbackValue='00:00'}" />

        <!-- command buttons -->
        <StackPanel Orientation="Horizontal" Grid.Column="1">
            <Button Content="Start" 
                    Command="{Binding StartCommand}" 
                    CommandParameter="{Binding ActiveItem}"
                    Visibility="{Binding ActiveItem.IsActive, Converter={StaticResource BoolToHiddenConverter}, 
                    FallbackValue={x:Static Member=pc:Visibility.Visible}}"                   
                    />
            <Button Content="Stop" 
                    Command="{Binding CancelCommand}" 
                    CommandParameter="{Binding ActiveItem}"
                    Visibility="{Binding ActiveItem.IsActive, Converter={StaticResource BoolToVisibleConverter}, 
                    FallbackValue={x:Static Member=pc:Visibility.Collapsed}}"
                    />
        </StackPanel>

    </Grid>
</Window>

A few extra applied stylings, and the Pomodoro app is shaping up nicely:

Not so bad Pomodoro

Next Steps

The next post, I’ll look at some of the new Windows 7 integration features available in WPF 4.0.

submit to reddit

Thursday, December 24, 2009

Twelve Days of Code – Pomodoro Object Model

As part of the twelve days of code, I’m building a Pomodoro style task tracking application and blogging about it. You can play along at home too. This post talks about the process of defining the object model and parts of the presentation model.

Most of the Model-View-ViewModel examples I’ve seen have not put emphasis on the design of the Model, so I’m not sure that I can call what I’m doing proper MVVM, but i like to have a fully functional application independent of its presentation and then extend parts of the model into presentation model objects. As I was designing the object model, I chose to use interfaces rather than concrete classes. There are several reasons for this, but the main factor was to apply a top-down Test-Driven-Development methodology.

On Top-Down Test-Driven-Development…

The theory behind “top-down TDD” is that by using the Application or other top-level object as the starting point, I only have to work with that object and its immediate dependencies rather than the entire implementation. As dependencies for that object are realized, I create a simple interface rather than a fully flushed out implementation -- I find using interfaces really helps to visualize the code’s responsibilities. Using interfaces also makes the design more pliable, in that I can move responsibilities around without having to overhaul the implementation.

This approach plays well into test-driven-development since tools like RhinoMocks and Moq can quickly generate mock implementations for interfaces at runtime. These dynamic implementations make it possible to define how dependencies will operate under normal (and irregular) circumstances which allows me to concentrate on the object I’m currently constructing rather than several objects at once. After writing a few small tests, I make a conscious effort to validate or rework the object model.

Using the Context/Specification strategy I outlined a few posts ago, the process I followed resembled something like this:

  • Design a simple interface (one or two simple methods)
  • Create the concrete class and the test fixture
  • After spending a few minutes thinking about the different scenarios or states this object could represent, I create a test class for that context
  • Write a specification (test) for that context
  • Write the assertion for that specification
  • Refine the context / subject-initialization / because
  • Write the implementation until the test passes
  • Refactor.
  • Add more tests.

(Confession: I started writing the ITaskApplication first but then switched to ITaskSessionController because I had a clearer vision of what it needed to do.) More on tests later, first let’s look more at the object model.

The Pomodoro Object Model

Here’s a quick diagram of the object model as seen by its interfaces. Note that instead of referring to “Pomodoro” or “Tomato”, I’m using a more generic term “Task”:

Pomodor.Core

In the above diagram, the Task Application represents the top of the application where the user will interact to start and stop (cancel) a task session. By design, the application seats one session at a time and it delegates the responsibility for constructing and initializing a task session to the Session Controller. The Task Application is also responsible for monitoring the session’s SessionFinished event, which when fired, the Application delegates to the AlarmController and SessionController to notify the user and track completion of the session.

Presently the TaskController acts primarily as a factory for new sessions and has no immediate dependencies, though it would logically communicate with a persistence store to track usage information (when I get around to that).

The TaskSession object encapsulates the internal state of the session as well as the timer logic. When the timer completes, the SessionFinished event is fired.

The Realized Implementation

Using a TDD methodology, I created concrete implementations for each interface as I went. At this point, the division between Presentation Model (aka ViewModel) and Controller Logic (aka Model) are clearly visible:

Pomodoro.Core.Implementation

To help realize the implementation, I borrowed a few key classes from the internets:

BaseViewModel

When starting out with the Presentation Model, I found this article as a good background and starting point for the Model-View-ViewModel pattern. The article provides a ViewModelBase implementation which contains the common base ViewModel plumbing, including the IDisposable pattern. The most notable part is the implementation for INotifyPropertyChanged which contains debug only validation logic that throws an error if the ViewModel attempts to raise a PropertyChanged event for a property that does not exist. This simple trick does away with stupid bugs related to ViewModel binding errors caused by typos.

I’ve also added BeginInitialization and EndInitialization members which prevent the PropertyChanged event from firing during initialization. This trick comes in handy when the ViewModel is sufficiently complicated enough that raising the event needlessly impacts performance.

For some reason, I prefer the name BaseViewModel over ViewModelBase. How about you?

DelegateCommand

When it came time to add Commands to my ViewModels, I considered brining Prism to my application primarily to get the DelegateCommand implementation. Perhaps I missed something, but I was only able to find the source code for download. Ultimately, I chose to take the DelegateCommand code-file and include it as part of the Core library instead of compiling the libraries for Prism. The decision to not compile the libraries was based on some tweaking and missing references for .NET 4.0, and the projects were not configured to compile against a strong-name which I would need for my strongly-named application.

The DelegateCommand provides an implementation of the ICommand interface that accepts delegates for the Execute and CanExecute methods, as well as a hook to raise the CanExecuteChanged event. At some point, I may choose to pull the implementation for the Start and Cancel commands out of the TaskApplicationViewModel and into separate classes.

More About the Tests

As promised, here is some more information about the tests and methodology. Rather than list the code for the tests, I thought it would be fun to list the names of the tests that were created during this stage of the development process. Because I’m using a context/specification test-style, my tests should read like specifications:

TaskApplicationSpecs:

  • when_a_task_completes
    • should_display_an_alarm
    • should_record_completed_task
  • when_a_task_is_cancelled
    • should record cancellation
  • when_a_task_is_started
    • should_create_a_new_session
    • ensure_new_tasks_cannot_be_started
    • ensure_running_task_can_be_cancelled
  • when_no_task_is_running
    • ensure_new_task_can_be_started
    • ensure_cancel_task_command_is_disabled
TaskSessionControllerSpecs:
  • when_cancelling_a_tasksession
    • ensure_session_is_stopped
  • when_creating_a_tasksession
    • should_create_a_task_with_a_valid_identifier
    • ensure_start_date_is_set
    • ensure_session_is_started
    • ensure_session_length_is_set
  • when_finishing_a_tasksession
    • ensure_session_is_stopped
TaskSessionViewModelspecs:
  • given_a_default_session
    • should_be_disabled
    • should_not_have_start_date_set
    • should_not_have_end_date_set
    • should_have_valid_id
  • when_session_is_ended
    • ensure_endtime_is_recorded
  • when_session_is_started
    • should_be_active
    • should_have_initial_time_interval_set
    • should_have_less_time_remaining_than_original_session_length
    • should_notify_the_ui_to_update_the_counter_periodically
    • should_record_start_time_of_task
    • ensure_end_time_of_task_has_not_been_recorded
  • when_timer_completes
    • should_raise_finish_event
    • ensure_finish_event_is_only_raised_once
    • should_run_the_counter_down_to_zero
    • should_disable_task
    • ensure_endtime_has_not_been_recorded

Next Steps

The next logical step in the twelve days of code is creating the View and wiring it up to the ViewModel.

submit to reddit

Twelve Days of Code - Solution Setup

As part of the Twelve Days of Code Challenge, I’m developing a Pomodoro style application and sharing the progress here on my blog.  This post tackles day one: setting up your project.

The initial stage of a project where you are figuring out layers and packaging is a critical part of the process and one that I’ve always found interesting.  From past experience, the small details at this stage can become massive technical debt later if the wrong approach is used, so it’s best to take your time and make sure you’ve crossed all the T’s and dotted the I’s.

Creating the Solution

For this project I’ve chosen to use Visual Studio 2010 Beta 2 and so far the experience has been great.  Visual Studio 2010 is going to reset the standard and bring new levels of developer productivity (assuming they solve some of the stability issues): it’s faster and much more responsive, eats less memory and adds subtle UX refinements that improve developer flow.  To get a better sense and to recreate this feeling, I urge you to load up Visual Studio 2003 and look at the Start page – we’ve come a long way.

The New Project window has a nice overhaul, and we can specify the target framework in the dialog.  Here I’m creating a WPF Application Pomodoro.Shell.  Note that I’m specifying to create a directory for the solution and that the Solution Name and Project Name are different. 

AddSolution 

Normally at this point I would consider renaming the output of the application from “Pomodoro.Shell.exe” to some other simpler name like “pomodoro.exe”.  This is an optional step which I won’t bother with for this application.

Adding Projects

When laying out the solution, the first challenge is determining how many Visual Studio Projects we’ll need, and there are many factors to consider including dependencies, security, versioning, deployment, reuse, etc.

There appears to be a school of thought that believes every component or module should be its own assembly, and I strongly disagree.  Assemblies should be thought of as deployment-units – if the components version and deploy together, its very likely that they should be a single assembly.  As Visual Studio does not handle large number of projects well, it’s always better to start with larger assemblies and separate them later if needed.

For my pomodoro app, I’ve decided to structure the project into two primary pieces, “core” and “shell”, where “core” provides the model of the application and “shell” provides the user-interface specific plumbing.

Add Test Projects

Right from the start of the project, I’m gearing towards how it will be tested.  As such, I’ve created two test projects, one for each assembly.  This allow me to keep the logical division between assemblies.

AddProject

As soon as the projects are created, the first thing I’ll do is adjust the namespaces of the test libraries to match their counterparts.  By extension, the tests are features of the same namespace but they are packaged in a separate assembly because I do not want to deploy them with the application.  I’ve written about this before.

FixNamespaceforTests

Configure common Assembly Properties

Once we’ve settled into a project structure, the next easy win is to configure the projects to share the same the assembly details such as version number, manufacture, copyright, etc.  This is easily accomplished by creating a single file to represent this data, and then linking each project to this file.  At a later step, this file can be auto-generated as part of the build process.

using System.Reflection;

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyCompany("Bryan Cook")]
[assembly: AssemblyCopyright("Copyright © Bryan Cook 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Tip: Link the AssemblyVersion.cs file to the root of each project, then drag it into the Properties folder.

Give the Assemblies a Strong-Name

If your code will ultimately end up on a end-user desktop, it is imperative to give the assembly a strong-name.  We can take advantage of Visual Studio’s built in features to create our strong-name-key (snk) but we’ll also take a few extra steps to ensure that each project has the same key.

  1. Open the project properties.
  2. Click on the Signing tab
  3. Check the “Sign the assembly” checkbox
  4. Choose “<New…>”
  5. Create a key with no password.
  6. Open Windows Explorer and copy the snk file to the root of the solution.
  7. Then for each project:
    1. Check the “Sign the assembly” checkbox
    2. Choose “<Browse…">”
    3. Navigate to the root of the solution and select the snk key.

Note that Visual Studio will copy the snk file to each project folder, though each project will have the same public key.

Designate Friend Assemblies

In order to aid testing, we can configure our Shell and Core assemblies to implicitly trust our test assemblies.  I’ve written about the benefits before, but the main advantage is that I don’t have to alter type visibility for testing purposes.  Since the assemblies have a strong name, the InternalsVisibleTo attribute requires the fully public key.

strong-name-internalsvisibleto

Since all the projects share the same key file, this public token will work for all the projects.  The following shows the InternalsVisibleTo attribute for the Pomodoro.Core project:

[assembly: InternalsVisibleTo("Pomodoro.Core.Tests, PublicKey=" +
"0024000004800000940000000602000000240000525341310004000001000" +
"1003be2b1a7e08d5e14167209fc318c9c16fa5d448fb48fe1f3e22a075787" +
"55b4b1cf4059185d2bd80cc5735142927fbbd3ab6eeebe6ac6af774d5fe65" +
"0a226b87ee9778cb2f6517382102894dc6d62d5a0aaa84e4403828112167a" +
"1012d5b905a37352290e4aa23f987ff2be3ccda3e27a7f7105cf5b05c0baf" +
"3ecbfd2371c0fa0")]

Setup External References

I like to put all the third-party assemblies that are referenced into the project into a “lib” folder at the root of the solution.  At the moment, I’m only referencing Moq for testing purposes.

A note on external references and source control: Team Foundation Server typically only pulls dependencies that are listed directly in the solution file.  While there are a few hacks for this (add each assembly as an existing item in a Solution Folder; or create a class library that contains the assemblies as content), I like to have all my dependencies in a separate folder with no direct association to the Visual Studio solution.  As a result, these references must be manually updated by performing a “Get Latest” from the TFS Source Control Explorer.  If you’ve got a solution for this – spill it, let’s hear your thoughts.

Setup Third-Party Tools

For all third-party tools that are used as part of the build, I like to include these in a “tools” or “etc” folder at the root of the solution.  This approach allows me to bundle all the necessary tools for other developers to allow faster ramp-up.  It adds a bit of overhead when checking things out, but certainly simplifies the build script.

Setup Build Script

There’s a few extra steps I had to take to get my .NET 4.0 project to compile using NAnt.

  1. Download the nightly build of the nant 0.86 beta1.  The nightly build solves the missing SdkInstallRoot build error.
  2. Paige Cook (no relation) has a comprehensive configuration change that needs to be applied to nant.exe.config
  3. Modify Paige’s version numbers from .NET 4.0 beta 1 to beta 2.  (Replace all references of “v4.0.20506” to “v4.0.21006”)

Here's a few points of interest for the build file listed below:

  • I’ve defined a default target “main”.  This allows me to simply execute “nant” in the root solution of the folder and it’ll take care of the rest.
  • The “main” target is solely empty because the real work is the order of the dependencies.  Currently, I’m only specifying “build”, but normally I would specify “clean, build, test”.
<project default="main">

  <!-- VERSION NUMBER (increment before release) -->
  <property name="version" value="1.0.0.0" />
  
  <!-- SOLUTION SETTINGS -->
  <property name="framework.dir" value="${framework::get-framework-directory(framework::get-target-framework())}" />
  <property name="msbuild" value="${framework.dir}\msbuild.exe" />
  <property name="vs.sln" value="TwelveDays.sln" />
  <property name="vs.config" value="Debug" />

  <!-- FOLDERS AND TOOLS -->
  <!-- Add aliases for tools here -->
  
  
  <!-- main -->
  <target name="main" depends="build">
  </target>

  <!-- build solution -->
  <target name="build" depends="version">

    <!-- compile using msbuild -->
    <exec program="${msbuild}"
      commandline="${vs.sln} /m /t:Clean;Rebuild /p:Configuration=${vs.config}"
      workingdir="."
          />

  </target>
    
  <!-- generate version number -->
  <target name="version">
    <attrib file="AssemblyVersion.cs" readonly="false" if="${file::exists('AssemblyVersion.cs')}" />
    <asminfo output="AssemblyVersion.cs" language="CSharp">
      <imports>
        <import namespace="System" />
        <import namespace="System.Reflection" />
      </imports>
      <attributes>
        <attribute type="AssemblyVersionAttribute" value="${version}" />
        <attribute type="AssemblyFileVersionAttribute" value="${version}" />
      </attributes>
    </asminfo>
  </target>

</project>

Next Steps…

In the next post, we’ll look at the object model for our Pomodoro application.

submit to reddit

Monday, December 14, 2009

Twelve Days of Code Challenge – 2009

Two years ago I tried an experiment in blogging for the festive season called the "Twelve Days of Code". The concept was to challenge myself to experiment in new technologies for at least an hour a day and blog about it. While I learned a lot about a focused topic (I chose Visual Studio Automation), the experiment didn't live up to my expectations.

This year, I want to do something different. I want to create a social experiment and challenge you!

The challenge

This year, the challenge is to write a simple Pomodoro style task tracking application. The application can be as simple or as far fetched as you want it to be, but at a minimum the application needs to:

  • Start, Stop and Cancel a Pomodoro
  • Notify the user when the pomodoro is complete

Of course, you don’t have to limit yourself to this functionality – sky’s the limit. If you want to collect usage statistics and provide reporting capabilities, persist a custom task list using SQLite, or work in the other characteristics of the pomodoro “flow” such as the 3-5 minute break between tasks – that’s up to you. Surprise me – and yourself!

In the spirit of Twelve Days of Code, pick a technology that’s new to you and do as much as you can. I'm planning on doing mine in .NET 4.0.

The rules

  • You can tackle any task in any order
  • Spend as much time as you want researching, but coding must be limited to one hour
  • Blog about it and leave a comment here
  • Have fun

What do I win?

The are no prizes, unfortunately. But if you are ever in downtown Toronto, there will be beers involved.

Here’s an outline of my twelve days:

  1. Solution Setup (build script, packaging, strong-names, etc)
  2. Object Model (application structure, commands, controllers)
  3. Presentation Model (View Models)
  4. Presentation templates (XAML, Converters, Data Templates)
  5. Composite Application setup (Prism)
  6. Dependency Injection Setup (Unity)
  7. Persistence Layer (record some stats using SQLite)
  8. Persistence Layer (Entity Framework 4.0)
  9. Animations (.NET 4.0 Visual State Manager)
  10. Windows 7 features (task bar icon overlays, action buttons, jump lists?)
  11. Installer (Wix)
  12. Functional Automation Testing

Good luck, Happy Coding and Happy Holidays.

submit to reddit

Saturday, March 01, 2008

Twelve Days of Code - Wrap up

Over the Christmas break, I started a series of posts about Visual Studio templates. I did some additional work, but never posted that information. I've got some new ideas for some code that I want to experiment and blog about and I may be afforded some additional time at work to pursue related issues, so hopefully I'll find the time to post about those.

Anyway, to clear out the cob-webs, here's the last segment in that series...

My experiment with the Multi-Item Template was to create two projects, create references between them, reference third-party assemblies and create a default class implementation. The biggest challenge and limitation to overcome is that the user supplied settings in the Multi-Item templates are not shared with each of the Project-Templates, resulting in the Project-Templates reverting to their default values. Very frustrating indeed. (Visual Studio 2008 apparently fixes this)

The best way to really manipulate the projects in a solution is to obtain a reference to the Project through the COM Interop libraries for Visual Studio. Once you have a reference to the project, you can fix the project name, add references, etc.

To overcome the limitations of the Multi-Item template, I used WizardExtensions in both the Multi-Item template and the Project-Templates, then used a singleton to carry settings between the projects.

This approached works, but seems pretty complicated, especially dealing with the COM Interop for Visual Studio. I still would need to strong-name the assemblies and write an installer that installs the templates and the assemblies.

It'll interesting to contrast this to the Guidance Automation Toolkit.

Friday, December 21, 2007

Debugging WizardExtensions for Visual Studio Templates

As per my previous post, this exercise would probably be much easier if I used the Guidance Automation Toolkit, but in the spirit of Twelve Days of Code, I promised to boldly venture into areas I normally don't go. I decided that I wanted to try out a WizardExtension so that I could compare the experience with the Guidance Automation Toolkit. So I created a new project and added the following references:

  • EnvDTE
  • ENvDTE80
  • Microsoft.VisualStudio.TemplateWizardInterface
  • System.Windows.Forms

The Visual Studio Template documentation says you need to sign your assembly and install it into the GAC, but that's crazy. Rather than jumping through hoops, I found a handy forum post that describes that the Visual Studio follows the standard assembly probing sequence, so the assembly needs to be in a place that the devenv.exe process can find it. Signing and installing into the GAC is simply a security measure. I didn't want to dump my custom assembly into Visual Studio's assemblies (where I would forget about it) so I created a custom folder in %program files%\Microsoft Visual Studio 8\Common7\IDE and added this to the probingPath of the devenv.exe.config. To enable debugging for my custom wizard-extension, I use two Visual Studio instances. One for my wizard-extension, the other for testing the template. Here are the steps involved:

  • Add the assembly and class name to your ProjectGroup.vstemplate file:
<wizardextension>
 <assembly>Experiments.TemplateWizard</assembly>
 <fullclassname>Experiments.TemplateWizard.CustomizeProjectNameWizard</fullclassname>
</wizardextension>
  • Zip up the updated template and copy it into the appropriate Visual Studio Templates folder.
  • Compile the wizard-extension assembly and copy it and its pdb to a path where visual studio can find it
  • Launch a new instance of Visual Studio
  • Switch back to the other visual studio instance, attach to the "devenv" process (the one that says it's at the start page) and set your break-points
  • Switch back to the new instance of Visual Studio and start the template that contains your wizard extension
  • debugging goodness!!

Well, at least I saved myself the effort of signing, etc. This exercise showed that very little is actually done at the ProjectGroup level of a Multi-Project template: the RunStarted is called, followed by ProjectFinishedGenerating method. The biggest disappointment is that the project parameter in the ProjectFinishedGenerating is null. This is probably because the item being created is a Solution, not a project.

The last ditch (seriously, ditch!) is to cast the automationObject passed into RunStarted to _DTE, and the work through COM interop to manage the Solution. That sounds romantic.

submit to reddit

Thursday, December 20, 2007

Bundling Visual Studio templates for distribution

Microsoft's done a fairly good job in packaging for Visual Studio templates. Simply:

  1. Create an xml file that adheres to the Visual Studio Content Installer Schema Reference
  2. Rename the xml with a "vscontent" extension
  3. Place the vscontent file and your template zip into another zip file
  4. Rename that zip file with a "VSI" extension.

Now, when you double click the VSI file it runs a wizard that installs your template into the appropriate Visual Studio Template folder.

submit to reddit

Wednesday, December 19, 2007

Visual Studio 2005 Multi-Project Templates - a waste of time?

As part of my twelve-days-of-code, I'm tackling a set of small projects geared towards simple project automation. I've discovered in recent projects that although the road is always paved with good intentions, other tasks, emergencies and distractions always prevent you from accomplishing what seem to be the most minor tasks. So when starting out on a new task, we always cut corners with the intention of returning to these trivial tasks whenever we find the time, or when they become justified in our client's eyes. However, if we started out with these things done for us, no one would question their existence or worry about a catch-up penalty; we would just accept these things as best-practice.

Visual Studio Project templates are interesting, though my first encounters with them suggest they miss the mark. For my projects, I find the effort isn't about creating the project, it's about creating the overall solution: project libraries, web sites, test harnesses, references to third-party libaries and tools, build-scripts, etc. Visual Studio supports the concept of "Multi-Projects Templates", which are limited (see below), but I suspect that the Guidance Automation Extensions might fill in the gaps.

Visual Studio supports two types of templates within the IDE, and a third type which must be stitched together using XML. The first type refers to "Item Templates" which refer to single files which can be included in any project. I'm focusing more on Project templates and Multi-Project templates.

Within Visual Studio, the concept of a project template is extremely easy: you simply create the project the way you like and then choose the "Export Templates..." option from the File menu. The project and its contents are published as a ZIP file in "My Documents\Visual Studio 2005\My Exported Templates". A big plus on the template structure is that all the files support parameterization, which means you can decorate the exported files with keywords that are dynamically replaced when the template is created by the user. The export wizard takes care of most of the keyword substitution for you, such that root namespaces in all files will match the name of the user's solution. With this in mind, a Project Template is "sanitized" and waiting for your client to adopt your structure with their name.

Multi-Project Templates stitch multiple Project Templates together by using a master xml-based template file. These templates can't be created using the IDE, but you can create a solution and then export each project out as a Project Template, then following this handy MSDN article and the Template Schema reference, you can quickly parcel together a master template.

However, there's a few really nasty limitations with multi-item projects templates. The biggest issue is that the Project Name cannot be parameterized, so the template adopts the names that are defined in your configuration file. As a result, the only thing you can really customize is the name of the solution. I was completely baffled by this: I thought I must be doing something wrong. However, after a few minutes of googling, others had come to the exact same conclusion.

Fortunately, the template system supports a Wizard framework, which would allow you to write some code to dynamically modify the solution. Unfortunately, the code for this would have to be strong-named and installed in the GAC. I'm tempted to wade into this, but I fear that I might be better off looking at the Guidance Automation Toolkit.

submit to reddit

Monday, December 17, 2007

Visual Studio Templates - Export Template not available

So I was started into my foray of the Twelve Days of Code, focusing on a "Software Automation" theme. First stop, "Visual Studio Project templates". I've played with these templates before, and because Visual Studio makes them considerably easy to do, this first stop should be an easy one. I had an interesting problem with Visual Studio that slowed me down.

The steps to create a template are straight forward: you create the item and then use the "Export Template" wizard in the "File" menu. However, the "Export Template..." option did not appear in the File menu.

I recently got a new laptop, and had to reinstall everything from scratch. At first I thought it was because IT only installed Visual Studio Professional instead of the Enterprise version. But there have been some other peculiarities, for example, the "Debug" tool bar was missing crucial items like "Step In", and "Step Out".

The culprit was that I had installed SQL Server 2005 after Visual Studio. Because they share the same shell (sounds a lot like the Component UI Application Block) SQL Server had changed the default settings for Visual Studio.

To fix:

  1. Select "Import and Export Settings..." from the Tools menu.
  2. Choose the option to "Reset all Settings."
  3. Choose the option to save your current settings, just in case.
  4. Pick an option that doesn't include "SQL Server". I chose the "Visual C# Development Settings"
  5. Finish

Perhaps the software-automation tip here is to configure your settings with defaults for your team, export them out and share the vssettings file (xml) the team.

Sunday, December 16, 2007

The Twelve Days of Code

One of the things I always have enjoyed over Christmas holidays is finding a few hours here and there for myself to explore new technolgies or tinker with side-projects. With all the events and distractions, finding time for yourself can be a pretty challenging task. This year, I'm thankful to have a lot of time off, so I've decided the best way to tackle this is to find projects that are interesting but don't require a huge investment of thought. So I'm not going to bother with cracking open the XAML specifications and trying a SilverLight project. Too much time. Too much thought.

So I've come up with the "Twelve Days of Code". Catchy, but not corny. Here's the rules:

  • Tackle a small project each day
  • Use technologies I haven't used before or wouldn't naturally use in the course of a work project
  • No project should take more than an hour.
  • If you get snagged, the hour is about the snag.
  • All the projects have to share a common theme
  • The projects need to provide value to me beyond the scope of the holidays.
  • Keep 'em blog worthy

I've decided my common theme should be "Software Automation" which is anything that saves time for repeated tasks. If I can save other developers on my team time, also great.

I've started a small list of to-do's, and I'm using http://www.rememberthemilk.com to help me with the scheduling, etc.

The list of thing I want to play with are:

  • Visual Studio Templates
  • Custom Installers / Wizards
  • Click Once deployment

I'll keep ya posted.