Tuesday, April 16, 2019

Agile Austin - Why 76% Of Organizations Are Failing At Agile

Why 76% Of Organizations Are Failing At Agile

David Hawks from AgileVelocity.com gave a great presentation to 50 Agilists at Agile Austin this week.

He used an interactive poll from PollEveryWhere.com which was a nice touch, so the audience could vote in real time on a question and we could see the results in a bar chart.

Four phases of change:

1. "Status Quo"

2. "Chaos and Resistance" When we introduce change the process always get worse.

3. "Integration and Practice" is next in which things slowly get better.

4. "New Status Quo" where things are genuinely better.

Four Agile Steps:

  1. Align

    Why are we going to Agile? It's not just to "do" Agile. Goal should be something like improve time to market, improve productivity, make happier customers, and have better quality.

  2. Learn

    Everyone needs to understand Agile.

  3. Predict

    We need to make things predictable before going faster.

  4. Accelerate

    This is where we actually start getting better.

  5. Adapt

    Try new things like Experiment Based Development

David had us do a small task in groups.

Why do so many companies struggle?

Most company think of Agile as a team level problem. Upper management just wants the team level to change, but not anything else. We need to change the System. We need to change the Organization, the leadership needs to understand Agility.

Three Impediments to Successful Agile Transformation

  1. Implementing solutions without clarity in desired results

    This produces:
    Lots of resistance and frustration
    Silo Optimization
    No clear measure of success

    We did another exercise on how the importance of different tasks to transform a culture.

    Steps to Organizational Change

    a. Create Urgency - "We have to get better,
        or our company may go bust."  (Comes for the top level)
    b. Form a powerful coalition
    c. Create a vision for change
    d. Communicate the vision
    e. Empower action
    f. Create quick wins
    g. Build on the change
    h. Anchor wins in culture
    
  2. No mechanism to resolve organizational level cross department impediments
        
    a. Impediments not resolved quickly
    b. Resistance is empowered
    c. Teams hit a ceiling and become disenfranchised
    

    Executives: We totally support agile, but what's the date, and what's the features?

  3. Leaders Not Creating Focus

    If the leaders say all projects are equally important - the teams have no priorities.

    So, the people with the least knowledge of corporate urgency, select the tasks that are coolest, easiest, and whose sponsor screams the loudest.

    Impact:
    a. lots of interruptions
    b. No time to improve
    c. no flow
    d. no ability to forecast
    e. slow time to value
    

David showed us how Agile Velocity evaluates how an Agile transformation is going.

Approach Agile by asking why, get buy in, break into smaller things.

Note to Self: How to Use NUnit with C# .Net in Visual Studio for the Mac

I always forget the three libraries to use NUnit with Visual Studio.
Note to self: Download these from NuGet:
  1. NUnit
  2. Microsoft.NET.Test.Sdk
  3. NUnit3TestAdapter

Then select "Run/Run Unit Tests" and VS will create a runner in the bottom pane.


PS: Latest endpoint to connect Visual Studio to the Nuget.org repository is

https://api.nuget.org/v3/index.json

You can put these directly in the csproj:

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
    <PackageReference Include="NUnit" Version="3.11.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
  </ItemGroup>

Friday, April 12, 2019

Smallest example I could think of using C# Async/Await and HttpClient.GetAsync() with Generics

Smallest example I could think of using HttpClient.GetAsync() with Generics.


using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace AsyncHttpClient
{
    /// <summary>
    /// Tiny example of using HttpClient.GetAsync() with Generics.
    /// Uses the REST API calls from the most excellent mysafeinfo.com for presidents and Beatles albums
    /// This prints:
    /// Requesting presidents
    /// Requesting Beatles albums
    /// ... waiting ...
    /// first president = number: '1','', party: '', term: ''
    /// first Beatles album = album name: 'Please Please Me (Mono)', date: '1963-03-22T00:00:00'
    /// </summary>
    public class President
    {
        public int president;
        public string name, party, term;
        public override string ToString() { return $"number: '{president}','{name}', party: '{party}', term: '{term}'"; }
    }
    public class BeatlesAlbum
    {
        public string album, date;
        public override string ToString() { return $"album name: '{album}', date: '{date}'"; }
    }

    class AsyncHttpClientExample
    {
         private static void Main()
        {
            string presidentsUrl = "https://mysafeinfo.com/api/data?list=presidents&format=json";
            string beatlesUrl = "https://mysafeinfo.com/api/data?list=beatlesalbums&format=json&select=ent,typ,rd&alias=ent=artist,typ=album,rd=date";
            var asyncHttpClientExample = new AsyncHttpClientExample();
            Console.Out.WriteLine("Requesting presidents");
            var presidents = asyncHttpClientExample.GetAsync<List<President>>(presidentsUrl);
            Console.Out.WriteLine("Requesting Beatles albums");
            var albums = asyncHttpClientExample.GetAsync<List<BeatlesAlbum>>(beatlesUrl);
            Console.Out.WriteLine("... waiting ...");
            Console.Out.WriteLine("first president = {0}", presidents.Result[0]);
            Console.Out.WriteLine("first Beatles album = {0}", albums.Result[0]);
        }
        private async Task<T> GetAsync<T>(string url)
        {
            HttpClient client = new HttpClient(new HttpClientHandler());
            HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false);
            var jsonString = response.Content.ReadAsStringAsync().Result;
            T result = JsonConvert.DeserializeObject<T>(jsonString);

            return result;
        }
    }
}