Myths of Agile

This is a post I’ve promised to write for a while, this isn’t a critic of ‘Agile’ in any of its guises but simply a guide to avoid incorrect statements.

Before I dive into this, let’s just remind ourselves of the Agile Manifesto;

Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan

That is, while there is value in the items on
the right, we value the items on the left more

Sprints therefore I’m Agile

A Sprint is essentially a time-box, nothing more nothing less. How the time-box is used depends on the team’s implementation. I’ve seen Sprints used to simply slice up months of development. Whilst I suspect that this practice is not uncommon I think most people would recognise a Sprint from definition popularised by the Agile strategy, getting close to process, of Scrum. Here a Sprint is typically used to create a small deliverable. There are many good reasons for this; quick feedback, leave in a deliverable state, focused priority based development, etc. However, a Sprint neither makes a development Agile nor it is necessary to be Agile. I say again, Sprint != Agile and Agile does not need Sprints.

Velocity will lead to predictable delivery

Another concept popularised by Scrum is that of a team’s Velocity. By attaching a notional cost to each item we deliver we can measure how long (or fast) a team takes to deliver them. Once we have the teams Velocity then we make better predictions about future deliveries. Once again I’m not going to judge the merits, or otherwise, of Velocity but I would like to point out the assumptions;

Velocity measurement is more accurate when you;

a) Retain the same team from Sprint to Sprint

b) The uncertainty/complexity of the tasks remains constant

When the team changes then Velocity becomes very suspect. How significant the change is will depend on the team changes but you need to be aware that it will affect the measurement.

Uncertainty/Complexity have always been the bugbear of software development and it is still true when using Velocity. Consider the concepts of Cynefin (taken from the excellent summary Agile Development and Retrospective Coherence)

clip_image001

Velocity is more useful when the tasks are in the ‘Order’ domains. These are the tasks that we fully understand regardless of if they are easy or complicated to implement. However, anything outside of that becomes an unknown. I.e. if your last Sprint was Ordered then you will have a velocity of O, but if your next Sprint in Complex then you are likely to have a very different velocity of C. This means that for the third Sprint your Velocity is (?)… O, C, O+C/2, etc. We cannot even say that all complex Sprints are always C. If you consciously look out for Complex tasks then you can mitigate them by converting them, as much as possible, to the Order domain via non-deliverable Spikes. In this strategy you honour the goal of velocity in the sense of knowing what will be soon be started, but not necessarily about stating how much you can deliver for any given future milestone.

Be warned, Velocity can be useful but it can also be very misleading. If you do choose to measure velocity then use it wisely.

Burn-down charts accurately show the state of the project

Another popular mechanism with Agile development is the Burn Down Chart. The premise is simple, start the graph with showing the amount of work to be done, and as the work is completed the graph will tend towards zero, i.e. the development has completed. However, in my experience this rarely shows an accurate view of the development. The problem is that teams do not stick with the items in a Sprint. Often other items creep in, be it additional features or bugs. Nothing wrong this, after-all we should be expecting change (not wishing to start a discussion about using the size of Sprint to mitigate this). The problem is that it is now very difficult to discern from old or new work. If the burn-down chart is a flat line is that telling you that you haven’t completed any work or that the input of work has matched the output? Whilst I’m struggling not to criticize Burn-Down charts it would remise not to mention Burn-Up charts that provide the same information but can also resolve this confusion. See Pawel Brodzinski’s excellent review of the issues.

Scrum or Kanban

This post has mentioned Scrum a few times, and there can be no denying its popularity with Agile devotees. Another popular strategy is that of Kanban. I have read a number of conversations that take the form of Scrum vs. Kanban and offer them up as a polar choice. Essentially Kanban is about assessing your current process and smoothing it out. If your current process, oh dear I’ve said process, is Scrum then you can apply Kanban to it. It’s not one or the other. In reality, if your development suits Kanban then over a period of re-assessment then you may find that many of the Scrum stages are also causing your bottlenecks and you will end up dissolving some of them, including Sprints. However, again that is not the conclusion of using Kanban, it is one possible outcome. It all depends on what best suits your particular issues.

 

Summary

I’ve had these conversations a number of times, so I hope other people will find it useful. When something is Agile, look back to the manifesto and evaluate the rationale. If it doesn’t help you with those goals then challenge why you should be using it.

About these ads
Posted in Agile, Development | Tagged , , , | Leave a comment

Custom Audio notifications with ToastNotificationManager

I struggled to find documentation for this, so I’ve blogged it here for future reference

    ToastTemplateType toastTemplate = ToastTemplateType.ToastText02;
    XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);

    XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
    toastTextElements[0].AppendChild(toastXml.CreateTextNode(title));
    toastTextElements[1].AppendChild(toastXml.CreateTextNode(message));

    var audio = toastXml.CreateElement("audio");
    audio.SetAttribute("src", "ms-appx:///MyAudio/CustomNotificationSound.mp3");
    audio.SetAttribute("loop", "false");

    toastXml.DocumentElement.AppendChild(audio);

    toastXml.DocumentElement.SetAttribute("launch", deepLink);
    ToastNotification toast81 = new ToastNotification(toastXml);
    ToastNotificationManager.CreateToastNotifier(MyAppId).Show(toast81);
Posted in Uncategorized | Leave a comment

Inspiron 15R SE 7520 fan always on?

Recently I’ve been getting worried about my Dell Inspiron overheating. The fan was noisy and air expelled was very hot. Looking at the processes running there didn’t seem to be any culprits. Looking at the device manager I noticed that after a recent Windows Update the AMD driver was no longer running. I went to the Dell support site and installed the latest Intel HD followed by (the order is important) the latest AMD drivers – note that these drivers are older than the ones Windows will install. Once installed the device manager showed they were both happy and the overheating seems to have been resolved. I’m guessing this is related to the horribly bungled dual video card implementation on the Inspiron. A more wild guess is that the AMD GPU was probably running all the time and the joint CPU/GPU cooler was probably struggling and hence the overheating problems.

Posted in Uncategorized | Leave a comment

1080p 6 inch Silverlight vs. Jupiter

Anyone know how to resolve this? Given the simple XAML;

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="3*"/>
        </Grid.RowDefinitions>

        <Border Background="Red"  Grid.Row="0" >
            <TextBlock Text="Silverlight"  />
        </Border>

        <Rectangle Fill="Blue" Grid.Row="1" />
        <Rectangle Fill="Green" Grid.Row="2" />

    </Grid>

This results in some very different results;

Silverlight Jupiter
image image

The Silverlight version scales nicely with the phone, whereas the Jupiter version renders the text without scaling it. How do you resolve this?

Posted in UniversalApps, Windows Phone | Tagged | 1 Comment

Controlling the StatusBar (SystemTray) in a Universal App

One of the problems of using Universal Apps is that some components only exist in one platform and not in another. One such example is the StatusBar (formally known as SystemTray) for Windows Phone 8.1. For example, to change the colour of the StatusBar you have to use code rather than xaml. This makes life a bit awkward when you want to use a shared page. So to avoid this issue I’ve created a User Control (ChromeController.xaml) that exists in both platforms;

image

The ChromeController is just dropped into the shared page like any other control, except this one doesn’t have any visuals (I could have used a real control, but I’m being lazy).

User Control

<UserControl
    x:Class="UniApp.ChromeController"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    />

Snippet from shared page;

<Grid>
            <local:ChromeController Background="Pink" Opacity="0.6" />

For the Windows 8.1 variant the code does absolutely nothing, although in the long term it could easily control win81 only assets. However, for the Windows Phone 8.1 it reuses the elements Background and Opacity settings and sets the StatusBar to the same values.

    public sealed partial class ChromeController : UserControl
    {
        public ChromeController()
        {
            this.InitializeComponent();

            this.Loaded += ChromeController_Loaded;
     
        }

        void ChromeController_Loaded(object sender, RoutedEventArgs e)
        {            
            var solidColorBrush = this.Background as SolidColorBrush;
            if (solidColorBrush != null)
            {
                var color = solidColorBrush.Color;
                var statusBar = StatusBar.GetForCurrentView();
                statusBar.BackgroundOpacity = this.Opacity;
                statusBar.BackgroundColor = color;
            }
        }
    }

Here’s the result.

image

Posted in UniversalApps | Tagged , , , | 2 Comments

Using Visual State Manager to share a Universal App page

I was having a chat about how Universal Apps work and how you might use the Visual State Manager to support both Win8 and Phone layouts in a single page.  Here goes;

image

  1. Create a new Universal App
  2. Cut MainPage.xaml from Windows 8.1 and paste it into Shared
  3. Delete MainPage.xaml from Phone
  4. Add a few simple Visual States to represent the screen sizes/orientations you want. In this case I have; MinimalOrPhonePortrailLayout, PortraitLayout, DefaultLayout
        <Grid>
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup>
                    <VisualState x:Name="DefaultLayout">
                    </VisualState>
                    <VisualState x:Name="MinimalOrPhonePortrailLayout">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Text" Storyboard.TargetName="SimpleMessage">
                                <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Phone Layout" />
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="PortraitLayout">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Text" Storyboard.TargetName="SimpleMessage">
                                <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Big Device Portrait" />
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid>
                <TextBlock Name="SimpleMessage" Text="Hello Default World" TextTrimming="WordEllipsis" Foreground="Blue" FontSize="60"/>
            </Grid>
        </Grid>
    
  5. Add a SizeChanged event to the page, this will be used to select the state
            public MainPage()
            {
                this.InitializeComponent();
    
                this.NavigationCacheMode = NavigationCacheMode.Required;
                this.SizeChanged += Page_SizeChanged;
            }
    
            void Page_SizeChanged(object sender, SizeChangedEventArgs e)
            {
                if (e.NewSize.Width < 520)
                {
                    VisualStateManager.GoToState(this, "MinimalOrPhonePortrailLayout", true);
                }
                else if (e.NewSize.Width < e.NewSize.Height)
                {
                    VisualStateManager.GoToState(this, "PortraitLayout", true);
                }
                else
                {
                    VisualStateManager.GoToState(this, "DefaultLayout", true);
                }
            }
    
  6. Add changes to the StoryBoards of the Visual States, in this quick example the text in a TextBlock will be changed.

Here’s the results;

image imageimageimage

imageimage

Hopefully you can see that it is possible to share a single page…although I’m not saying you should ;)

Posted in UniversalApps | Tagged , , , | 1 Comment

HttpClient redirect gotcha

Just a quick post as I’ve just fallen foul of this.

Recently I changed by web-client to use the nice await/async HttpClient, e.g.

   
  HttpClient client = new HttpClient();   
  string result = await webClient.GetStringAsync(serviceRequest); 

The problem is that my service decided to be a good web citizen and change their API by sending a redirect. Unfortunatley the above code simple fell over…legs in the air.

The trick is to configure the HttpClient to allow redirects;

   
  HttpClientHandler handler = new HttpClientHandler();   
  handler.AllowAutoRedirect = true;   
  HttpClient webClient = new HttpClient(handler);            
  string result = await webClient.GetStringAsync(serviceRequest); 
Posted in Windows Phone | Tagged , , | Leave a comment