Tracks part one

Snap - Back to reality, oh there went gravity, oh there goes Rabbit (hole)

This was the first post I started to write, and the previous has been steps to get here.

To get started learning .NET Core 3, I’m building a Tracks App, and the goal is basically to implement it using as many technologies as possible.

The plan was not to rebuild the blog, but hey!

The App

Model first

The app is a simple app, which allows you to track stuff. What stuff is is loosely defined: Name, time and a payload. Later I will probably add a bit more structure. A Track is defined by a name, and it has a list of steps. A Step also has a name, a timestamp and a payload. The payload may be gathered automatic and can contain things like geo position, or other telemetry. All should be bound for one User.

Just because I want to test the code highlight of Jekyll A naive implementation of tracker could be something like this

using System;
using System.Collections.Generic;

namespace d6.Tracks {
    public class Tracker {
        var tracks = new Dictionary<string, Track>();

        public Track GetOrAddTrack(string name) { 
            Track t = GetTrack(name);
            if (t != null) return t;
            t = AddTrack(name);
            return t;
  
        }

        public Track AddTrack(string name) {
            if (tracks.ContainsKey(name)) {
                throw new Exception("Track Exists!");
            } else {
                Track t = new Track(name);
                tracks.Add(name, new Track(name));
                return t;
            }
        }

        public Track GetTrack(string name) {
            if (tracks.ContainsKey(name)) {
                return tracks[name];
            } else {
                return null;
            }
        }
        public Step AddStep(string track) {
            return GetOrAddTrack(track).AddStep();
        }

    }
}

Console app second

The next part is to implement a command line interface for tracking stuff. For now just a simple class for adding and listing tracks and steps. The goal is to have a command line language like git or the amazing azure AZ command.

c:\> track add "Code Track" "Having fun"
"Having fun" added to track "Code Track"

c:\> track list 
[Code Track]
2019-10-21 22:39 : Having fun

CommandLineParser

To implement the command line argument parsing I found this medium post by @ozdemirv called “Parsing Command Line Arguments in .Net (Core) Console Applications”. The post referrers to CommandLineParser (github page, nuget page) , which I installed in my console app in Visual Studio Nuget package manager as other packages:

 
PM> Install-Package CommandLineParser

The CommandLineParser allows me to map verbs at lease in one level, but I have not yet figured out if I can do nested, but in any case that is not needed just yet. I will do my best to separate each part of the app as I want to re-implement it on other platforms The command line parsing is not really that beautiful, but it does describe the mapping quite nicely:

    [Verb("add", HelpText = "add a track")]
    class AddOptions {
        [Value(0, MetaName = "Name", HelpText = "Name of track", Required = true)]
        public string Name { get; set; }

        [Value(1, MetaName = "Description", HelpText = "Step description", Required = false)]
        public string Description { get; set; }
    }

In The main app you simply map the options to a handler method:

static int Main(string[] args) {
    System.Console.WriteLine("Tracks!");
    return CommandLine.Parser.Default.ParseArguments<AddOptions, ListOptions>(args)
        .MapResult(
        (AddOptions opts) => Add(opts),
        (ListOptions opts) => List(opts),
        errs => 1
        );
}
        

In the handler method ywe implement the logic for adding the track and step

static readonly Tracker tracker = new Tracker();

public static int Add(AddOptions options) {
    
    System.Console.WriteLine($"Adding step to {options.Name}");
    if (String.IsNullOrEmpty(options.Description)) {
        return tracker.AddStep(options.Name) != null ? 0 : -1;
    } else {
        return tracker.AddStep(options.Name, options.Description) != null ? 0 : -1;
    }
    
}

This must be it for tonight.


CHANGELOG

2019-10-30
  • Interfaces to class diagram
2019-10-20
  • Console and Model