Starred notes from CodeMash 2016

0
January 10, 2016 // irl

I had another great experience at CodeMash this year and would like to once again share some highlights.

Please keep in mind this is only my paraphrasing or lessons learned from each talk, and may not be even remotely accurate of what the speaker was trying to convey.  We all hear what we want to hear.. 😉

7 Languages in 7 Hours – Amber Conville

  • We covered Ruby, Clojure, Haskell, Rust, Scala, Elixir and Go – exercising the same kata in each
  • Ruby was the most elegant and simple (my opinion)
  • Clojure was the most awkward with its ((heavy (use) of (parentheses)) (my (opinion(s))))
  • When you exercise the same simple kata 7 times, the differences between the languages become a lot more muted and the algorithms/approaches stand out

[Factory] Fun with Machine Learning – Jennifer Marsman

  • 3 primary classes of algorithms
    • Classification (Discrete answers)
    • Regression (Continuous answers)
    • Clustering (Answer unknown, group things that are alike together)
  • Azure has made it crazy easy to get up and running quickly
  • Domain knowledge is really helpful to sniff test results

Humanitarian Toolbox Hack for Good (Day 2, Part 2) – Tony Surma

  • ASP.NET 5 is back to the command line (currently, rumor has it that it’s changing)
  • My past AppVeyor/NPM experience is reusable
  • It’s easy to step in and solve detailed technical problems, without broader context

Node.js Crash Course – David Neal

  • Node.JS utilizes an asynchronous single-threaded message pump, forcing you into pit of success (callback/async patterns)
  • node-inspector lets you debug through Chrome
  • Edge.JS will let you run .NET code in a Node.JS process

Building Angular 2.0 Applications with TypeScript – Bill Wagner

  • Angular 2.0 is built using TypeScript
  • Can set breakpoints on TypeScript source within the browser
  • There’s a lot of special characters in use (parentheses, brackets, asterisks, pounds)
  • Main benefits of TypeScript are avoiding injector errors (typos) and better IntelliSense

Designing C# 7 in the Open – Kevin Pilch-Bisson

  • Limit design meetings to 8-10 people to avoid design by (large) committee
  • ~40 people work on Roslyn
  • Considering a lot of features.. a few particularly interesting ones:
    • Non-null by default
    • Records (i.e. very basic class type)
    • Strong types for data over the wire (e.g. JSON)
    • Pattern matching / switching on type

From Developer to Manager – Sean O’Connor

  • Coding is not doing your job
  • Management is a learn-able skill, just like a new language
  • Management is about setting the tone for the team
  • While tempting to let issues self-resolve, need to be very wary about letting things fester

Design for Non-Designers from a Non-Designer – Jay Harris

  • Primary principle of design is usability, which is familiarity
  • There are rules and they can be broken, but as a novice follow them
  • Developers hate repetition (monochrome), and want to abstract it into a class 😉
  • Contrast will always draw the eye, control the contrast in your design

Why I Left Angular and Knockout for React – Cory House

  • React is not a framework, it’s a library
  • React puts JavaScript and HTML into the same file, as they’re closely coupled
  • React only supports one-way flow to force developer to think through data flow
  • Angular embraces HTML, React embraces JS

You CAN Kanban – Steve Smith

  • 2 rules – Visualize the work, minimize in progress
  • Optimize for flow (time from conception to completion) over utilization (maxing out the developers, which leads to context switching and inefficiencies)
  • When prioritizing, avoid low/medium/high.. you’ll never do anything but high

ASP.NET 5: How to Get Your Cheese Back – Tugberk Ugurlu

  • Complete rewrite, only “concept compatibility”
  • Project content is inherent from folders (no .csproj)
  • Project output is explicit in webroot folder
  • Configuration hierarchy is explicitly defined, no more transforms
  • No ties to msbuild at all, gulp instead for client-side building

Art And Code: Make Useless Things – Jamison Dance

  • Art recognizes value in the process of creation, and in the thing that is created in itself – not just in the utility of what the creation does which is how we generally evaluate code
  • Code can be art, with or without great utility
  • All of the worst things in coding (estimation, status meetings, micro management) can be jettisoned so the best things in coding (creation from nothing, imagination) can flourish when making something useless
  • Happiness and laughter are worth creating, so useless things may not be actually useless at all
  • If you only code for utility, you are missing out on opportunities

How to Add S.P.I.C.E. to Your Speaking – Maureen Zappala

  • Something memorable gets revisited
  • We all have stories, we’re just not convinced of their value
  • Most important process of a speech is the thought process the audience undertakes
  • Vocal variety and body language are important

Software Development Lessons Learned from Industrial Failures in the 1980s – Charlotte Chang

  • US GM automotive plant in Fremont, CA in 60’s-70’s – one of the worst work forces in automotive
  • Closed plant and opened a new one following Toyota processes/principles
  • Same individuals that were horrible and dissatisfied in the former, were successful and happy in the latter.
  • Process can transform people.

Program some health into your life – Stan Jonsson

  • You can train yourself to eat almost anything if you give it a month
  • Slip-ups happen – not a reason to slip up more
  • The best cardio is the one you find most enjoyable
  • Weight training steers your body to burn fat over muscle
  • Open debate in weight lifting about 1 set providing 80% of the value of 4 sets
  • Need to keep changing routines, body adjusts and you don’t get the same value

Cross-Platform Desktop Apps with Electron – David Neal

  • Electron apps are written in HTML/CSS/JS
  • Electron apps are packaged/run within Node.JS + Chrome
  • You don’t need permission to be awesome

Summary

If you haven’t been to CodeMash, you should check it out.  There’s a great community, great content and a very modest cost.  My sincere appreciation and gratitude to all of the speakers, organizers and everyone who helps participate to make it all possible. 🙂

WPF TreeView with Multi Select

0
November 22, 2015 // wpf

The WPF TreeView is very powerful, but out of the box it doesn’t support selecting multiple items at once.  By multiple selection I mean holding down the control key or shift key to select a set of items, similar to behavior available in other controls such as Windows Explorer.

To support enhancements like dragging and dropping multiple items at once to CodeMaid‘s Spade tool window, we wanted this capability to multi select.  There’s several different solutions out there, and in particular our implementation is largely based on the great work of Cristoph Gattnar available here.

Christoph’s solution utilizes attached properties.  Our solution converted this to a behavior and added support for arrow keys and the space bar for more keyboard navigation scenarios.

Here’s a little example of it working in action:

Multi-Select

Multi-Select

The living code can be found within CodeMaid’s open source repository here.

And just in case, here’s a static snapshot of the code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace SteveCadwallader.CodeMaid.UI
{
    ///

<summary>
    /// A behavior that extends a <see cref="TreeView"/> with multiple selection capabilities.
    /// </summary>


    /// <remarks>
    /// Largely based on http://chrigas.blogspot.com/2014/08/wpf-treeview-with-multiple-selection.html
    /// </remarks>
    public class TreeViewMultipleSelectionBehavior : Behavior<TreeView>
    {
        #region SelectedItems (Public Dependency Property)

        ///

<summary>
        /// The dependency property definition for the SelectedItems property.
        /// </summary>


        public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(
            "SelectedItems", typeof(IList), typeof(TreeViewMultipleSelectionBehavior));

        ///

<summary>
        /// Gets or sets the selected items.
        /// </summary>


        public IList SelectedItems
        {
            get { return (IList)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }

        #endregion SelectedItems (Public Dependency Property)

        #region AnchorItem (Private Dependency Property)

        ///

<summary>
        /// The dependency property definition for the AnchorItem property.
        /// </summary>


        private static readonly DependencyProperty AnchorItemProperty = DependencyProperty.Register(
            "AnchorItem", typeof(TreeViewItem), typeof(TreeViewMultipleSelectionBehavior));

        ///

<summary>
        /// Gets or sets the anchor item.
        /// </summary>


        private TreeViewItem AnchorItem
        {
            get { return (TreeViewItem)GetValue(AnchorItemProperty); }
            set { SetValue(AnchorItemProperty, value); }
        }

        #endregion AnchorItem (Private Dependency Property)

        #region IsItemSelected (TreeViewItem Attached Property)

        ///

<summary>
        /// The dependency property definition for the IsItemSelected attached property.
        /// </summary>


        public static readonly DependencyProperty IsItemSelectedProperty = DependencyProperty.RegisterAttached(
            "IsItemSelected", typeof(bool), typeof(TreeViewMultipleSelectionBehavior),
            new FrameworkPropertyMetadata(OnIsItemSelectedChanged));

        ///

<summary>
        /// Gets the IsItemSelected value from the specified target.
        /// </summary>


        /// <param name="target">The target.</param>
        /// <returns>The value.</returns>
        public static bool GetIsItemSelected(TreeViewItem target)
        {
            return (bool)target.GetValue(IsItemSelectedProperty);
        }

        ///

<summary>
        /// Sets the IsItemSelected value on the specified target.
        /// </summary>


        /// <param name="target">The target.</param>
        /// <param name="value">The value.</param>
        public static void SetIsItemSelected(TreeViewItem target, bool value)
        {
            target.SetValue(IsItemSelectedProperty, value);
        }

        ///

<summary>
        /// Called when the IsItemSelected dependency property has changed.
        /// </summary>


        /// <param name="obj">The dependency object where the value has changed.</param>
        /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private static void OnIsItemSelectedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var treeViewItem = obj as TreeViewItem;
            var treeView = treeViewItem?.FindVisualAncestor<TreeView>();
            if (treeView != null)
            {
                var behavior = Interaction.GetBehaviors(treeView).OfType<TreeViewMultipleSelectionBehavior>().FirstOrDefault();
                var selectedItems = behavior?.SelectedItems;
                if (selectedItems != null)
                {
                    if (GetIsItemSelected(treeViewItem))
                    {
                        selectedItems.Add(treeViewItem.DataContext);
                    }
                    else
                    {
                        selectedItems.Remove(treeViewItem.DataContext);
                    }
                }
            }
        }

        #endregion IsItemSelected (TreeViewItem Attached Property)

        #region Behavior

        ///

<summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>


        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.AddHandler(UIElement.KeyDownEvent, new KeyEventHandler(OnTreeViewItemKeyDown), true);
            AssociatedObject.AddHandler(UIElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(OnTreeViewItemMouseUp), true);
        }

        ///

<summary>
        /// Called when the behavior is being detached from its AssociatedObject, but before it has
        /// actually occurred.
        /// </summary>


        protected override void OnDetaching()
        {
            base.OnDetaching();

            AssociatedObject.RemoveHandler(UIElement.KeyDownEvent, new KeyEventHandler(OnTreeViewItemKeyDown));
            AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(OnTreeViewItemMouseUp));
        }

        #endregion Behavior

        #region Event Handlers

        ///

<summary>
        /// Called when a TreeViewItem receives a key down event.
        /// </summary>


        /// <param name="sender">The sender.</param>
        /// <param name="e">
        /// The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.
        /// </param>
        private void OnTreeViewItemKeyDown(object sender, KeyEventArgs e)
        {
            var treeViewItem = e.OriginalSource as TreeViewItem;
            if (treeViewItem != null)
            {
                TreeViewItem targetItem = null;

                switch (e.Key)
                {
                    case Key.Down:
                        targetItem = GetRelativeItem(treeViewItem, 1);
                        break;

                    case Key.Space:
                        if (Keyboard.Modifiers == ModifierKeys.Control)
                        {
                            ToggleSingleItem(treeViewItem);
                        }
                        break;

                    case Key.Up:
                        targetItem = GetRelativeItem(treeViewItem, -1);
                        break;
                }

                if (targetItem != null)
                {
                    switch (Keyboard.Modifiers)
                    {
                        case ModifierKeys.Control:
                            Keyboard.Focus(targetItem);
                            break;

                        case ModifierKeys.Shift:
                            SelectMultipleItemsContinuously(targetItem);
                            break;

                        case ModifierKeys.None:
                            SelectSingleItem(targetItem);
                            break;
                    }
                }
            }
        }

        ///

<summary>
        /// Called when a TreeViewItem receives a mouse up event.
        /// </summary>


        /// <param name="sender">The sender.</param>
        /// <param name="e">
        /// The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the
        /// event data.
        /// </param>
        private void OnTreeViewItemMouseUp(object sender, MouseButtonEventArgs e)
        {
            var treeViewItem = FindParentTreeViewItem(e.OriginalSource);
            if (treeViewItem != null)
            {
                switch (Keyboard.Modifiers)
                {
                    case ModifierKeys.Control:
                        ToggleSingleItem(treeViewItem);
                        break;

                    case ModifierKeys.Shift:
                        SelectMultipleItemsContinuously(treeViewItem);
                        break;

                    default:
                        SelectSingleItem(treeViewItem);
                        break;
                }
            }
        }

        #endregion Event Handlers

        #region Methods

        ///

<summary>
        /// Selects a range of consecutive items from the specified tree view item to the anchor (if exists).
        /// </summary>


        /// <param name="treeViewItem">The triggering tree view item.</param>
        public void SelectMultipleItemsContinuously(TreeViewItem treeViewItem)
        {
            if (AnchorItem != null)
            {
                if (ReferenceEquals(AnchorItem, treeViewItem))
                {
                    SelectSingleItem(treeViewItem);
                    return;
                }

                var isBetweenAnchors = false;
                var items = DeSelectAll();

                foreach (var item in items)
                {
                    if (ReferenceEquals(item, treeViewItem) || ReferenceEquals(item, AnchorItem))
                    {
                        // Toggle isBetweenAnchors when first item is found, and back again when last item is found.
                        isBetweenAnchors = !isBetweenAnchors;

                        SetIsItemSelected(item, true);
                    }
                    else if (isBetweenAnchors)
                    {
                        SetIsItemSelected(item, true);
                    }
                }
            }
        }

        ///

<summary>
        /// Selects the specified tree view item, removing any other selections.
        /// </summary>


        /// <param name="treeViewItem">The triggering tree view item.</param>
        public void SelectSingleItem(TreeViewItem treeViewItem)
        {
            DeSelectAll();
            SetIsItemSelected(treeViewItem, true);
            AnchorItem = treeViewItem;
        }

        ///

<summary>
        /// Toggles the selection state of the specified tree view item.
        /// </summary>


        /// <param name="treeViewItem">The triggering tree view item.</param>
        public void ToggleSingleItem(TreeViewItem treeViewItem)
        {
            SetIsItemSelected(treeViewItem, !GetIsItemSelected(treeViewItem));

            if (AnchorItem == null)
            {
                if (GetIsItemSelected(treeViewItem))
                {
                    AnchorItem = treeViewItem;
                }
            }
            else if (SelectedItems.Count == 0)
            {
                AnchorItem = null;
            }
        }

        ///

<summary>
        /// Clears all selections.
        /// </summary>


        /// <remarks>
        /// The list of all items is returned as a convenience to avoid multiple iterations.
        /// </remarks>
        /// <returns>The list of all items.</returns>
        private IEnumerable<TreeViewItem> DeSelectAll()
        {
            var items = GetItemsRecursively<TreeViewItem>(AssociatedObject);
            foreach (var item in items)
            {
                SetIsItemSelected(item, false);
            }

            return items;
        }

        ///

<summary>
        /// Attempts to find the parent TreeViewItem from the specified event source.
        /// </summary>


        /// <param name="eventSource">The event source.</param>
        /// <returns>The parent TreeViewItem, otherwise null.</returns>
        private static TreeViewItem FindParentTreeViewItem(object eventSource)
        {
            var source = eventSource as DependencyObject;

            var treeViewItem = source?.FindVisualAncestor<TreeViewItem>();

            return treeViewItem;
        }

        ///

<summary>
        /// Gets items of the specified type recursively from the specified parent item.
        /// </summary>


        /// <typeparam name="T">The type of item to retrieve.</typeparam>
        /// <param name="parentItem">The parent item.</param>
        /// <returns>The list of items within the parent item, may be empty.</returns>
        private static IList<T> GetItemsRecursively<T>(ItemsControl parentItem)
            where T : ItemsControl
        {
            if (parentItem == null)
            {
                throw new ArgumentNullException(nameof(parentItem));
            }

            var items = new List<T>();

            for (int i = 0; i < parentItem.Items.Count; i++)
            {
                var item = parentItem.ItemContainerGenerator.ContainerFromIndex(i) as T;
                if (item != null)
                {
                    items.Add(item);
                    items.AddRange(GetItemsRecursively<T>(item));
                }
            }

            return items;
        }

        ///

<summary>
        /// Gets an item with a relative position (e.g. +1, -1) to the specified item.
        /// </summary>


        /// <remarks>This deliberately works against a flattened collection (i.e. no hierarchy).</remarks>
        /// <typeparam name="T">The type of item to retrieve.</typeparam>
        /// <param name="item">The item.</param>
        /// <param name="relativePosition">The relative position offset (e.g. +1, -1).</param>
        /// <returns>The item in the relative position, otherwise null.</returns>
        private T GetRelativeItem<T>(T item, int relativePosition)
            where T : ItemsControl
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            var items = GetItemsRecursively<T>(AssociatedObject);
            int index = items.IndexOf(item);
            if (index >= 0)
            {
                var relativeIndex = index + relativePosition;
                if (relativeIndex >= 0 && relativeIndex < items.Count)
                {
                    return items[relativeIndex];
                }
            }

            return null;
        }

        #endregion Methods
    }
}

We made it back to Kalamazoo X this year for another day of soft skills, and I have to say it was even better the second time around. 🙂

Similar to the CodeMash post a couple months ago, here’s my set of bullet point take-away’s from each of the sessions.  They may be taken out of context, and are absolutely tainted with my perspective and interpretation – but hopefully they encourage you to catch these talks at other conferences.  Every one of the speakers had a great message and is worth taking the time to hear.

Note: You can also get excerpts from each of the talks at the conference site here and see a lot of chatter on Twitter at #kalx15

Jeff Blankenburg (@jeffblankenburg) – Be A Beginner

  • Beginners learn, experts know.  Wouldn’t you rather be learning?
  • Somebody being better than you, doesn’t mean you’re not an expert (i.e. there’s not only one expert).
  • After 7-8 years, inspiration fades.. then what?
  • Give permission to fail, it encourages risk taking.

Cori Drew (@coridrew) – Ignition: Geek Parenting’s Lessons Learned…so far

  • Git is a gateway drug (amen).
  • The saying “Those who can, do; those who can’t, teach” is not true at all for our industry.
  • Kids learn much better from each other than adults.
  • Let your kids epic fail, you don’t have to sugar coat everything.

Jim Holmes (@aJimHolmes) – Growing Into Leadership

  • Who can you help be more awesome?
  • You’ll seldom regret stepping away from the keyboard.
  • Give your team a safe place.
  • A leader makes their team awesome, not themselves.

Alan Stevens (@alanstevens) – Values Driven Development

  • In software, there’s always compromise.  There is no flawless system.
  • It doesn’t matter how well you build the wrong thing.
  • The standard you walk past is the standard you accept.

Cory House (@housecor) – Confessions of a Technical Speaker: A Behind-the-Scenes Tour

  • Manufacture urgency to get things done.
  • I’m not the best, nor am I the worst.  That’s OK and I can still be valuable.
  • Risk is an irreversible bad outcome.  What is truly irreversible?
  • People chose you over alternatives, they want you to succeed.

Jay Harris (@jayharris) – Conviction

  • Talent is critical, and more important than passion.
  • Find yourself at the end of each day better than when you started.
  • Success shouldn’t be hitting your goals, it should be all the milestones on the way.
  • Figure out your talents, get paid to use them.

Dawn E. Kuczwara (@digitaldawn) – Give Up!

  • To pick up something new, you must let go of something old.
  • Figure out what you are still doing that isn’t helping you to your goals.
  • Holding on to something may be blocking somebody else’s chance to grow.

Elizabeth Naramore (@ElizabethN) – The Beauty of a Beginner’s Mind

  • Todo’s are a long pointless grind.
  • The more you do something, the more your brain will grow to accommodate.
  • Time spent learning is never wasted.
  • You have 2.5hrs each day where you account to nobody.

Summary

Kalamazoo X is well worth the time, very open and inviting, and extremely affordable.  Thanks again to the speakers, participants and most of all organizers for making it so memorable. 🙂

As I’m starting to dabble with Gulp, it is wonderful to see support for it already well underway within Visual Studio.  Kudos to Microsoft/Mads Kristensen for embracing a community solution and making it compatible with the IDE we love.  There’s a lot of wonderful articles out there by Scott Hanselman, John Papa, Dave Paquette and others talking about what these tools are and how to get them up and running in Visual Studio.  I’m not going to recap any of it here as it’s already been well stated. 🙂

What I didn’t find out there was how do I take Gulp the rest of the way out to a production server?  Specifically, how can I get Gulp to run via MSbuild on a TFS2013 CI build server, and then make sure that output can be picked up and deployed via Web Deploy?  Works on my machine is great, but I <3 my CI and automated deployments.  Here’s what I learned that can take us the rest of the way to Works in my build and deployment pipeline.

Note: With the solution below, you don’t need to have the Task Runner Explorer extension by Mads Kristensen as referenced in the articles – but it can still be pretty helpful for visualizing output or ad hoc runs.

Phase 1: Conquer the universe

Whoa, whoa, slow down.  Can’t I just simply use pre-build events or post-build events?

Excellent question, let’s try it.

Pre-build events (spoiler: too soon)

Pre-build events

The commands are pretty straight-forward. We make sure we’re in the project directory on the build server, we call npm install to pull down our dependencies, and then we call out to Gulp.  This looks great, and it seems to work locally.. sometimes.

Wait, sometimes?

In my case I’m utilizing TypeScript.  What’s happening is that on a rebuild (or clean build), TypeScript has removed all the JavaScript files (or they haven’t been built yet) and there’s nothing for Gulp to find.  On a second build, Gulp finds the old JavaScript output and then it works.  Two compile passes isn’t going to fly.

Alright, pre-build events are out – let’s wait until after the build so we know all the TypeScript->JavaScript compilation is complete.

Post-build events (spoiler: too late)

Post-build events

Same setup, we’ll just try it a little later.

Now our Gulp output is getting generated (yay!).. but it happens too late to be picked up by Web Deploy which actually occurs prior to post-build (boo!).

So pre-build is too soon, and post-build is too late.  It’s time to turn to custom targets in our .csproj file.  Trust me, it sounds scarier than it really is – we’re devs, we’ve got this. 😉

Extending our .csproj with custom targets (just right)

Manually edit your .csproj file and at the bottom (must be after all Import lines) we’re going to add some new content.

  <PropertyGroup>
    <CompileDependsOn>
      $(CompileDependsOn);
      GulpBuild;
    </CompileDependsOn>
  </PropertyGroup>
  <Target Name="GulpBuild" DependsOnTargets="CompileTypeScript">
    <Exec Command="npm install" />
    <Exec Command="gulp" />
  </Target>

What we have done here is specify a PropertyGroup to extend the existing CompileDependsOn target to add our own custom target called ‘GulpBuild’.  On our target, we can specify other targets that need to happen first – such as CompileTypeScript.  Now we know that TypeScript compilation will happen first, and we’re in the pipeline long before deployment occurs.  For more details, check out this article on MSDN or Sayed Ibrahim Hashimi’s wonderful book on MSBuild.

What about triggering a gulp cleanup script when we clean our solution in Visual Studio?  It’s a very similar extension:

  <PropertyGroup>
    <CompileDependsOn>
      $(CompileDependsOn);
      GulpBuild;
    </CompileDependsOn>
    <CleanDependsOn>
      $(CleanDependsOn);
      GulpClean
    </CleanDependsOn>
  </PropertyGroup>
  <Target Name="GulpBuild" DependsOnTargets="CompileTypeScript">
    <Exec Command="npm install" />
    <Exec Command="gulp" />
  </Target>
  <Target Name="GulpClean">
    <Exec Command="gulp clean" />
  </Target>

Fantastic.  At this point, we’re now able to run Gulp both locally within Visual Studio as well as part of our build process!

Hooking into Web Deploy

So what’s left?  Well, by default Web Deploy isn’t going to pick up any of our output from the Gulp pipeline since it isn’t a part of the project.  So we need to explicitly point it at our build output.  There’s a couple helpful articles that talk about the approach in more detail on ASP.net and by Sam Stephens.

  <PropertyGroup>
    <CopyAllFilesToSingleFolderForPackageDependsOn>
      $(CopyAllFilesToSingleFolderForPackageDependsOn);
      CollectGulpOutput;
    </CopyAllFilesToSingleFolderForPackageDependsOn>
    <CopyAllFilesToSingleFolderForMsdeployDependsOn>
      $(CopyAllFilesToSingleFolderForMsdeployDependsOn);
      CollectGulpOutput;
    </CopyAllFilesToSingleFolderForMsdeployDependsOn>
  </PropertyGroup>
  <Target Name="CollectGulpOutput">
    <ItemGroup>
      <_CustomFiles Include="build\**\*" />
      <FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
        <DestinationRelativePath>build\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
      </FilesForPackagingFromProject>
    </ItemGroup>
    <Message Text="CollectGulpOutput list: %(_CustomFiles.Identity)" />
  </Target>

This is a bit harder to read, but in essence again we are extending existing targets with our own custom target. That target is collecting any files that exist in a ‘build’ folder (you can replace the 2 occurrences of ‘build’ with ‘dist’ or whatever folder convention you use), and synchronizing them across into the deployment package with the same folder structure.

Bringing it all together

Combining those pieces we’ve now got a project setup that will run Gulp both locally and on the build server, is compatible with TypeScript generating JavaScript, and is compatible with Web Deploy. If you’re raising your arms in triumph here.. thanks for joining me. 😉

  <PropertyGroup>
    <CompileDependsOn>
      $(CompileDependsOn);
      GulpBuild;
    </CompileDependsOn>
    <CleanDependsOn>
      $(CleanDependsOn);
      GulpClean
    </CleanDependsOn>
    <CopyAllFilesToSingleFolderForPackageDependsOn>
      $(CopyAllFilesToSingleFolderForPackageDependsOn);
      CollectGulpOutput;
    </CopyAllFilesToSingleFolderForPackageDependsOn>
    <CopyAllFilesToSingleFolderForMsdeployDependsOn>
      $(CopyAllFilesToSingleFolderForMsdeployDependsOn);
      CollectGulpOutput;
    </CopyAllFilesToSingleFolderForMsdeployDependsOn>
  </PropertyGroup>
  <Target Name="GulpBuild" DependsOnTargets="CompileTypeScript">
    <Exec Command="npm install" />
    <Exec Command="gulp build --mode $(ConfigurationName)" />
  </Target>
  <Target Name="GulpClean">
    <Exec Command="gulp clean" />
  </Target>
  <Target Name="CollectGulpOutput">
    <ItemGroup>
      <_CustomFiles Include="build\**\*" />
      <FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
        <DestinationRelativePath>build\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
      </FilesForPackagingFromProject>
    </ItemGroup>
    <Message Text="CollectGulpOutput list: %(_CustomFiles.Identity)" />
  </Target>

Bonus round – conditional gulp

    <Exec Command="gulp build --mode $(ConfigurationName)" />

You may have noticed I snuck something else in the final version – passing the build configuration into Gulp as a command line argument called mode. Using tools like yargs and gulpif you can then tailor your Gulp pipeline (e.g. not running uglify in ‘Debug’ mode).  If you want more details please post a comment.

Other approaches

After posting this article, I ran into two other approaches solving the same problem in slightly different ways.  All three of our posts have been in March, so clearly this is the month for automating builds. 😉  Here’s links to those alternative ways:

Summary

By utilizing custom targets in our .csproj file, we’re able to utilize npm and Gulp consistently both on our local Visual Studio instance and on our TFS build server.  We can also make sure our generated build output is picked up by Web Deploy and lands on our servers.

Thanks again to all the referenced authors and articles for guiding me to this solution.  No promises this is the only way (or even a good way) to do it, but it works for me and hopefully gives you some ideas too. 🙂  Please chime in on the comments any thoughts, questions or improvements!

Starred notes from CodeMash 2015

1
January 15, 2015 // irl

I was fortunate enough to get to attend CodeMash once again this year and wanted to share some of the great information I picked up.  These bullets are highlights from my notes and may be (i.e. definitely are) tainted with my own opinions/perspectives.  So if you dislike/disagree with anything, don’t judge the speaker blame the messenger. 😉

Metaprogramming – Kathleen Dollard

  • “Only write code that only you can write”
  • Metaprogramming is a broad subject, but specifically talked a lot about code generation via T4 and Roslyn
  • Five principles to metaprogramming – you control the results, metadata is distinct and flexible, metaprogramming should be the easiest way to get it done, human crafted code is sacred, resulting code is the highest quality
  • Good metaprogramming characteristics are very similar to code principles (e.g. DRY, SoC)
  • Consider partial classes and file extension conventions to isolate generated code from human code

Interviewing – Kerri Miller

  • Define your culture – are you a bunch of independent cowboys or do you work in a pair programming style?
  • Have people from diverse roles involved as interviewers – you’ll gain more perspectives on the candidates.
  • Write down your impressions immediately afterwards – avoid a group-think bias.
  • Consider a pair programming audition where neither of you have any foreknowledge of the problem.
  • Collect metrics – register your predictions before-hand and keep tabs on people you don’t hire (false negatives).

C# 6 – Dustin Campbell

  • Primary constructors (the syntax where you had parameters right on the class definition) have been pulled out due to complexity/confusion
  • Expression bodied members can really cut down code size when you have simple return methods
  • Extension methods may become a lot more popular as you will now be able to explicitly pull in only the set of extension methods you want with the new “using static XYZ” syntax
  • C# 6 design is complete
  • C# 7 design will begin soon, moving Roslyn from CodePlex to GitHub, finalizing VS2015

HTML5 Web Components – Cory House

  • Web components in ES6 will make it much easier to share/grab modules that bundle up HTML/CSS/JS together
  • You’ll be able to extend native HTML controls
  • There is a Shadow DOM concept that allows for areas of isolated scope that will help isolate components

Swift – Ravi Desai

  • Swift looks a lot more like Java/C/C# code now
  • Contains some quirks (e.g. two ways to do function calls) for inter-operability with Objective-C

Innovation – Dustin Updyke

  • Proposes that ideas should be tracked (e.g. Trello) and it needs to be part of your culture to foster/encourage ideas
  • Evaluate ideas on interest, value, feasibility and ability
  • “As you think so shall you become” – Bruce Lee
  • Most innovations come from rigorous examinations and hard work, not sparks in a vacuum
  • Same principles that apply within business can apply to yourself as an individual

Xamarin – Jesse Liberty

  • Xamarin platform (non-UI) gets you about 50% code reuse across mobile devices
  • Xamarin forms (UI) can get you up to about 90% code reuse
  • Xamarin forms utilizes XAML and MVVM, is extremely similar to WPF/Silverlight
  • Check out Falafel University

Roslyn – Jon Skeet

  • Roslyn can replace some unit tests you may be writing as code suggestions in VS
  • Bill Wagner is coordinating a public repository for Roslyn helpers
  • The Syntax Tree Visualizer is your friend for doing any work with Roslyn

Social Developer – Seth Juarez

  • You should punch people in the face
  • Ask meaningful questions, don’t need another weather conversation
  • If something didn’t go well, you can still ask “what did you learn”

Agile – Paul Holway

  • FDA medical device software can be done in an Agile environment
  • Cadence is important; It sets a framework for change without interruption
  • Don’t demo until after QA and refactoring – or you’re putting more cats into the wall than you can afford to get out
  • You won’t be able to do it all – be honest about where you’re lacking
  • Option from the crowd – consider a chat room vs. a meeting for daily scrum

Selling Fiddler – Eric Lawrence

  • Have metrics to establish a price
  • Make something, and share it

Developer Flow – Rob Keefer

  • Flow (happiness) comes from a goal, feedback and a balance between challenge and skill
  • Week level – write a plan, have a board to track progress, identify your skill gaps
  • Day level (Pomodoro) – write down task(s), track your progress/interruptions, ensure tasks can be accomplished
  • Moment level (TDD) – write a test, run the test, gain confidence as you pass each piece
  • Shut down e-mail/phone/etc. for as long of stretches as possible (ex: 2hrs)

Long Lived Code Base – Jeremy Miller

  • Architecture can’t be set in stone
  • Have living documentation as part of your build process
  • Diagnostics will be critical over time, invest in them

Growing Beyond Independent – Jay Harris

  • Showed his talk outline as a full screen of icons (no text) then went through each in turn
  • An interview is really about setting expectations, in both directions
  • You have to trust your employees
  • Learn to delegate – not that you can’t do it, it’s that you could be doing something else

C# On Arduino – Eric Potter

  • Scriptcs lets you quickly write and run C# from the command line
  • Chocolatey is an excellent way to install tools on Windows
  • Arduino runs C and is half the cost of Netduino which runs C#
  • Utilizing scriptcs, a library pushed to Arduino and a USB connection Arduino can be made to run C#
  • Want: Build a missile launch type system where two key turns are required to push to production

Summary

CodeMash is an awesome conference that I highly recommend.  Thanks again to all of the speakers, conference organizers, sponsors and my employer Quintiles. 🙂

I have a Visual Studio solution that includes several different potential startup projects, and I find myself frequently switching between them the hard way through the solution explorer.  It is enough of an irritant that I started developing a new capability into CodeMaid to provide a quick way to switch between startup project(s).  I made it about a third of the way in (Card 171) when I discovered something fantastic..

Somebody else had already done it!  Even better than writing code to solve one of your problems is finding someone else who has done it for you! 😉

Behold SwitchStartupProject, a free Visual Studio extension by Andreas Bilger.

How to get it?

Simply search for “SwitchStartupProject” under Visual Studio’s Tools->Extensions and Updates.  Or here’s a direct link.

How does it work?

In the Visual Studio toolbar you’ll see a new drop down that lists the current startup project.

Toolbar

Toolbar

You can open the drop down and see all of the projects in the solution and choose a different startup project.

Dropdown

Dropdown

Well that’s nice, but do I really need to see my unit test projects and other projects that can’t really be started?  Well lets drop down to Configure…

Mode

Mode

Smart mode sounds good, and it does just what you would expect – limits the list to the right kind of project types that can be started.

Dropdown Filtered

Dropdown Filtered

Excellent.  Now I also like to set multiple startup projects at once (e.g. a client project and a server project).  What have you got for me there?  Back to the configuration options where we can setup profiles that contain more than one startup project.

Multiple Projects

Multiple Projects

Now our defined profile(s) will appear as an option in the dropdown menu.

Dropdown Multiple

Dropdown Multiple

How active is it?

Well, he beat me by a week to publishing a VS14 CTP compatible version.. so lets call it very active. 😉  To check out the source and more head to the project home here: https://bitbucket.org/thirteen/switchstartupproject/

Summary

This plugin is exactly what I had in mind to build.  My gratitude to Andreas Bilger for building this excellent little tool so now I don’t have to and I can keep coding away on other features. 🙂  I’ve just started playing with it so if you have any comments or experience with it, please sound off below.

I’ll be attending That Conference this week. If you’re in the Wisconsin Dells neighborhood and want to say hi send me a tweet (@codecadwallader). 🙂

It is no secret that I’m a huge fan of JetBrains – most notably for their well beloved tool ReSharper.  🙂  Once you’ve spent some time with the tool and its very impressive feature suite, you really won’t be able to work without it anymore.  With so many features, there may be some that slip through the cracks.  So today let’s take a look at a feature you may not have experimented with before – ReSharper’s Structural Search and Replace.

The code transform

Through the INotifyPropertyChanged series, we learned how to simplify our boilerplate code from

public int Iterations
{
    get { return _iterations; }
    set
    {
        if (_iterations != value)
        {
            _iterations = value;
            OnPropertyChanged("Iterations");
        }
    }
}

to

public int Iterations
{
    get { return GetPropertyValue<int>(); }
    set { SetPropertyValue(value); }
}

Fantastic, but who wants to manually make that code change over and over again?

Setting up a Search and Replace pattern

ReSharper’s Structural Search and Replace lets you define a code pattern with some variable substitutions in order to pick up a code pattern. So let’s try it out. 🙂

  1. Highlight the code you want to update. This will help auto-populate the search.
  2. Launch ReSharper’s Structural Search and Replace tool (a.k.a. Search with Pattern)

    ReSharper Structural Search And Replace Menu

    ReSharper Structural Search And Replace Menu

  3. Extend the Find section as needed. In this example the OnPropertyChanged was not included by default. My first attempt was to add
    OnPropertyChanged("$propname$");

    but it wouldn’t match the code so I don’t think placeholders inside strings are accepted. Instead I added

    OnPropertyChanged($str$);

    where str is a placeholder I added that is an expression of type string.

    ReSharper Structural Search and Replace - Find

    ReSharper Structural Search and Replace – Find

  4. Select the Replace button in the top right hand corner to open up a second pane where you can fill out the replacement pattern using the same placeholders as defined in the find section.

    ReSharper Structural Search And Replace - Replace

    ReSharper Structural Search And Replace – Replace

  5. Click the Replace button in the bottom right and ReSharper will search for all matches and show you a confirmation dialog where you can enable/disable individual instances to replace.

    ReSharper Structural Search And Replace - Confirmation

    ReSharper Structural Search And Replace – Confirmation

  6. Enjoy!

Saving Your Pattern

To take it one step further, with ReSharper you can also save this pattern and make it a part of their normal code analysis.

  1. Reopen the Search with Pattern dialog and click Save in the bottom right.

    ReSharper Structural Search And Replace - Save

    ReSharper Structural Search And Replace – Save

  2. To quickly open the dialog they are talking about, click the pattern catalog icon in the top right next to the Replace radio button.

    ReSharper Structural Search And Replace - Toolbar

    ReSharper Structural Search And Replace – Toolbar

  3. When you go to the pattern catalog you’ll see your new pattern which you can set to different severity levels for code analysis to determine how urgently ReSharper flags it.  Suggestion seemed like a good level to me.

    ReSharper Structural Search And Replace - Pattern Catalog

    ReSharper Structural Search And Replace – Pattern Catalog

Now when you’re browsing your code, ReSharper will flag your code pattern.

ReSharper Structural Search And Replace - Suggestion

ReSharper Structural Search And Replace – Suggestion

Provide the Quick Fix replacement you defined.

ReSharper Structural Search And Replace - Quick Fix

ReSharper Structural Search And Replace – Quick Fix

And you’re golden. 🙂

ReSharper Structural Search And Replace - Updated

ReSharper Structural Search And Replace – Updated

Summary

ReSharper’s Structural Search and Replace is an excellent tool for identifying and updating those old code patterns or smells.  It does take some work and potentially trial and error to get the patterns right, but automating busy work is what we developers do best. 🙂

For more details you can check out ReSharper’s documentation.

Here’s an export of the pattern we built in this blog post
INotifyPropertyChanged_ReSharper_Pattern.zip
I hope it helps and if you’ve got any great patterns of your own, please share them in the comments. 🙂

I’m always on the quest for better coding tools, and a new one I’ve been playing with for the last couple weeks is a code search tool called Entrian Source Search. It is a Visual Studio plugin that maintains an index of your code base for rapid search results. Not free – $29/dev after a 30-day trial.

How does it work?

When you open a solution for the first time, you are prompted if you want to create an index and if so which path(s) you want to monitor.

Entrian New Solution image

New Solution prompt

Entrian Setup Index image

Setup index dialog

I especially liked the option to “Share another solution’s index”.  It is those little details that show a project’s maturity.

Why not just use the built-in Find in Files?

  • Indexed searches are exceptionally faster
  • Highlighted results are easier to skim
  • A results grid that shows the matches in the same place instead of just dumping them at the end of a path
  • When folders/files/lines are repeated, the entries after the first are grayed out a little which is a nice visual cue of repetition
  • Right-click context menu with several convenient refinements/actions
  • More keyboard shortcuts (the way to my heart)
  • Searching your code base (instead of your solution) will pick-up all those hard to find usages in configuration files, reflection usages, etc. that may get missed otherwise.  Yes, you can configure Find in Files to search folders – but have you?

See for yourself:

Visual Studio Find Results image

Visual Studio Find Results

Entrian Search Results image

Entrian Search Results

Entrian Search Results Context Menu image

Entrian Search Results Context Menu

What about other tools on the horizon?

I’ve been using TextCrawler for a long time, and it is still my tool of choice to run a search without bringing up Visual Studio.  It is free and runs quick, but the UI could use some love (e.g. keyboard shortcuts, respond to window size changes).  This tool is unfortunately not very active (sad trombone).

What I’m really interested in watching is Sando.  I’ve been trading e-mails with its lead David C. Shepherd and they come to the search game with an intent to go far beyond a simple grep.  Out of ABB Research and with the help from some developers in the community they are building an engine that prioritizes search results, offers auto-completion and is focused on research-driven functionality.  Sure it will support an exact match search like the others (*yawn*), but what it does that makes it stand apart is fuzzy searching like a true search engine.  The concept is amazing for discovery in a new code base, or all of those times you can’t exactly remember what you called that method.  It currently only searches code files within the solution which is a deal breaker for me, but I’m excited to see how the product evolves as it is very active and growing.  If you’re looking for an open source project to join (besides CodeMaid of course 😉 ) – then I would definitely encourage you to take a look at Sando (source on CodePlex) and be a part of its future.  It is available on Visual Studio Gallery if you want to give it a whirl or check out their new website for more details.

Sando

Sando

Summary

Entrian Source Search is my recommendation for today, but my hopes for the future are with Sando.  If you have any other code search tool recommendations then speak up in the comments. 🙂

Welcome back for part 3 in this INotifyPropertyChanged series. This time we’ll be taking a look at reversed notifications which are another code smell with this pattern.

Reversed notifications

What do I mean by reversed notifications? When you have a dependent property (FullName) which is calculated based on an independent property (FirstName) then you have to make sure you raise notifications for FullName whenever FirstName changes. Since there isn’t a direct way to do this, a common approach is to have the source directly do the work for the destination:

        public string FirstName
        {
            get { return GetPropertyValue<string>(); }
            set
            {
                if (SetPropertyValue(value))
                {
                    RaisePropertyChanged("FullName");
                }
            }
        }

        public string FullName
        {
            get { return string.Format("{0} {1} {2}", FirstName, MiddleName, LastName); }
        }

It works, but it is putting the knowledge of the dependency between the properties in the wrong place. With this approach, the independent property (FirstName) has to be aware of all of its dependencies (FullName). It would be much better if the dependent property could take care of itself. So how do we flip this around in the right direction?

NotifiesOnAttribute

Using attributes, we can specify our dependencies directly on the dependent property – leaving the independent property untouched!

        public string FirstName
        {
            get { return GetPropertyValue<string>(); }
            set { SetPropertyValue(value); }
        }

        [NotifiesOn("FirstName")]
        public string FullName
        {
            get { return string.Format("{0} {1} {2}", FirstName, MiddleName, LastName); }
        }

Magic! 😉

Ok, lets peek behind the scenes to see how that is being accomplished. We have defined a NotifiesOnAttribute class which simply takes a string parameter pointing to the independent property. We’ve also set the AttributeUsage to allow for the property to be defined multiple times. So in our example above we can also be notified when MiddleName and LastName change by repeating the attribute definition. In our view model, we do a lazy-initialized pull of all the attribute definitions on our class and store them in an ILookup structure which is basically a dictionary without unique keys. Finally when we are raising property changed, we check our cache of dependent properties and if any are found then we raise PropertyChanged on them as well.

        private ILookup<string, string> _dependentLookup;

        private ILookup<string, string> DependentLookup
        {
            get
            {
                return _dependentLookup ?? (_dependentLookup = (from p in GetType().GetProperties()
                                                                let attrs = p.GetCustomAttributes(typeof(NotifiesOnAttribute), false)
                                                                from NotifiesOnAttribute a in attrs
                                                                select new { Independent = a.Name, Dependent = p.Name }).ToLookup(i => i.Independent, d => d.Dependent));
            }
        }

        protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (propertyName == null) throw new ArgumentNullException("propertyName");

            var propertyChanged = PropertyChanged;
            if (propertyChanged != null)
            {
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));

                foreach (var dependentPropertyName in DependentLookup[propertyName])
                {
                    RaisePropertyChanged(dependentPropertyName);
                }
            }
        }

Tada!

Performance

We’re almost done, but we still have to check out our performance. I’ve modified the sample application (below) that raises a million notifications using both mechansims. Here’s the results:

Performance image

Performance comparison between direct and attribute based mechanisms.

Our baseline took 9.565s, and our attribute approach took 10.099s – just about a 5% increase which works for me. 🙂

Summary

With attributes on our dependent property, we can not only cut down our code but we can also put our logic back in the right place. Thanks for reading these article(s). I hope you enjoyed them and if you have other ideas on how to improve the INotifyPropertyChanged pattern please chime in on the comments. 🙂

Code: SteveCadwallader.NotifyPropertyChanged.3of3.zip

Part 1: INotifyPropertyChanged (1 of 3) – without the strings
Part 2: INotifyPropertyChanged (2 of 3) – without the backing fields