Apprentice Dev Blog: Week 5 - Looking To The Future

  • Friday, Jun 17, 2022
A person stands, looking up into the night sky. They are quite far from the camera and shown only in silhouette against a multi coloured starfield. The sky is a yellow hue, going through purple into green before becoming black.

The cover image for this post is by Greg Rakozy

This blog post was written by Alex. Alex is our apprentice for 2022, and will be providing frequent developer logs.


Jamie here - to jump directly to Alex’s log for this week, click here

Today marks the completion of Alex’s fifth week with us, meaning that they are halfway through their apprenticeship.

remember that Alex is NOT their real name

Alex is studying a Digital T-Level course and has joined us for their mandatory eight weeks in industry.

We are incredibly proud to be helping with Alex’s technical education. And as a reminder, I was assigned to be their PM on the project that they are working on and someone to reach out to for help in completing it. The Digital T-Level course that Alex has taken is very comprehensive and covers a number of different development technologies, but there are certain gaps in their knowledge. This is not meant as a negative point towards either the course designers or those who are delivering it, there is simply not enough time to teach all of the things required of a developer in just two short years.

in fact, development is one of the career choices which require a person to be constantly learning new things

We’re finally getting ready to move on to the .NET Maui portion of this project. There are a few reasons for waiting until now:

  • it gives the .NET Maui content creators a chance to content in line with the v1 release of .NET Maui
  • it gives us a chance to make sure that Alex’s project is shored up with enough tests
  • it gives Alex experience at taking an already working project and upgrading parts of it
  • Alex has built this project with SOLID principles in mind, so they should be able to just swap the UI with very few issues

I’m still very aware that with .NET Maui being so new the documentation and content around it could be incorrect, as was pointed out by our friend Scott Harden:

.NET Maui really is at the bleeding edge, and there isn’t that much documentation out there - and what there is is partially incorrect because it’s so new. My recommendation would be to go WPF first, then .NET Maui.

- Scott

But I feel that there is enough content out there for Alex to get started on their journey of learning .NET Maui; and there will be a lot to learn - with MVVM, XAML, and a different paradigm for building and releasing. As a reminder, my goal for this project has never been for Alex to complete it; I would much rather that they were able to use this project as a way to plug any gaps in their knowledge around how we actually do things in industry.

they’ll also get a great app code base to work with once they have completed their apprenticeship

Anyway, you didn’t come here to read what I have to say. So here is a development log which represents Alex’s fifth week, in their own words:

one note, I’ve edited for presentation not content


Alex’s Devlog

Hi, I’m Alex and am currently studying a Digital T-Level course, am taking my industry experience with RJJ Software, and these are some of the things that I learned this week.

The early part of this week was spent finishing off some unit tests for my services

Jamie here: you can read about Alex’s work on unit testing here

with these tests in place, both Jamie and I were happy that we could swap the user interface technology and not have to worry about breaking anything from the service layer down. This fits hand in hand with the SOLID principles:

  • Single-responsibility Principle
  • Open-closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

I haven’t discussed what either the “Open-close principle” or the “Liskov Substitution principle” are yet, so let’s change that now.

Liskov Substitution Principle

This is a complicated way of saying that if we have two objects which inherit from a common base object, then they can each be substituted with the other.

Let’s say we have something like:

public interface IRepository <T> where T : class
{
  int Get<T>(Guid id);
}

public class DataRepository<T> where <T> : class
{
  public int Get<T>(Guid id)
  {
    throw new NotImplementedException();
  }
}

public class SomeOtherRepository<T> where <T> : class
{
  public int Get<T>(Guid id)
  {
    throw new NotImplementedException();
  }
}

because both DataRepository<T> and SomeOtherRepository<T> inherit from the same base interface (i.e. IRepository <T>), they can be used in place of each other.

To put that in a much simpler way, imagine we have three classes:

public class Shoe
{
  public int Armour { get; set; } = 0;
  public int Fancyness { get; set; } = 0;
  public int Speed { get; set; } = 0;
}

public class DressShoe : Shoe
{
  public DressShoe()
  {
    Speed = -10;
    Fancyness = 50;
  }
}

public class RunningShoe : Shoe
{
  public RunningShoe()
  {
    Speed = 100;
    Fancyness = 25;
  }
}

we can consume a Shoe class in a method like this:

public class Person
{
  private Feet feet;
  public Person()
  {
    feet = new Feet();
    feet.initialize();
  }
  public void EquipShoe(Shoe shoeToEquip)
  {
    this.Feet.Equipped = shoeToEquip;
  }
}

and the EquipShoe method will happily take either an instance of Shoe, DressShoe, or RunningShoe because of Polymorphism. This is what we’re leveraging when we are injecting our dependencies into the services and such:

private static void ConfigureServices(IServiceCollection services, string connectionString)
{
    services
        .AddTransient(typeof(IRepository<>), typeof(Repository<>));
}

Where this line:

.AddTransient(typeof(IRepository<>), typeof(Repository<>))

is saying to the .NET dependency injector:

Whenever I ask for a type which matches the type definition of IRepository, regardless of the constraint, give me a matching Repository with a matching constraint

Open-closed principle

The Open-closed principle states that classes should be open to extension, but closed to modification.

You don’t want to change a class once it has been created and consumed by some other class. This is because a change in the code is a chance for you to mess things up and break stuff. Even with tests in place, you don’t want to change a class unless it has a direct need to change.

Adding methods to a class without altering it in C# and .NET is by using something called Extension methods. Let’s take our Shoe class from above, any changes we make to the Shoe class will need to trickle down to the DressShoe and RunningShoe classes, too. But if we created an extension method, we wouldn’t have to alter the Shoe, DressShoe, or RunningShoe classes.

public static class ShoeExtensions
{
  public static void ResetStats(this Shoe myShoe)
  {
    myShoe.Armour = 0;
    myShoe.Speed = 0;
    myShoe.Fancyness = 0;
  }
}

This way we can reset the statistics on an instance of our Shoe class, or any classes which inherit from it, without changing the class makeup.

.NET Maui

In preparation for swapping the user interface for something more modern, I’ve been taking two .NET Maui courses:

These two are great resources for learning .NET Maui and were recommended by Jamie. I would recommend watching through the entire set of videos because they talk through thing like MVVM, XAML, dependency injection, and how to get the tools set up on your machine.

Jamie here: combined, there are eight hours of content

With Gerald’s course, I was able to get the required tools setup and installed on my machine, including the Android emulator and the Java Development Kit (JDK). The JDK is required because Android applications are usually written in either Java or Kotlin

Jamie here: Kotlin is JetBrains' Java-like language. It’s also possible to write Android apps using either C++ or React Native

There are repos for both Gerald’s crash course) and James', too. I’d recommend taking a look at both repos as they are both achieving similar things but in slightly different ways.

Jamie here: it can be a good idea to get more than one point of view on new things sometimes

There’s nothing wrong with Gerald’s crash course, but I liked James' way of explaining things a little more. I might also take a look at the .NET Podcasts repo if there is time, but Jamie has advised against looking into this right now, as it uses a lot of features that I don’t need

Jamie here: signalr, chat, local storage, synchronisation, etc.

Here are some screenshots of James' application running on my machine. First as an Android application:

A collection of screenshots from the .NET Maui workshop application. The code is running in the Windows Android emulator, oriented as portrait, and shows a series of rows, each representing a different monkey. Each row has an image of the monkey on the left, the name of the monkey species as a header, and a rough location under that. The central screenshot shows a message box applied over the application with the legend &quot;Henry Phoenix&quot;. The righthand side screenshot is similar to the first, but it has a darkened theme applied (all light colours are swapped with dark ones, except for in the images of the monkeys)
left to right: the result of pressing the "Get Monkeys" button; the result of clicking the "Find Clostest" and what the app looks like when the system is in dark mode

And here’s a single screenshot of the same code running as a Windows application:

A single screenshot representing the same code but run as a fullscreen Windows application. It has the same detail as the previous screenshots, however this time the application is oriented in a landscape manner.

My goal for next week is to use the knowledge that I’ve gained this week and start building on a .NET Maui user interface for the project I’m working on. Once I have a non-functional user interface, I’ll start moving the business logic services over and start wiring things up to make it functional.

This should be relatively easy… once I have a user interface in place. Because I’m new to XAML, it might take a me a little longer than it took to put the original WinForms user interface together.

Jamie here: at the time of writing, there are no WYSISYG tools for building .NET Maui user interfaces like the WinForms one


Jamie again.

Another week of setting Alex some pretty complicated tasks, and another week of watching them fly through those tasks with ease. I can’t wait to see what Alex is able to create with .NET Maui’s XAML toolkit. I’ve been asking Alex to fill me in as to what they’ve learned this week, because .NET user interfaces passed me by very quickly over the last 12-13 years or so. I’ve spent the majority of my career on the server side, and building basic HTML, CSS, and JavaScript front ends, so all of this is new to me too.

Being realistic, I knew that Alex wouldn’t complete all of the requirements set (the project is a greenfield project representing a CRM system with the ability to generate PDF invoices), but I knew that there would be enough business logic for them to sink their teeth into whilst learning the things that I wanted them to learn. But looking at the time we have left, I’m pretty confident that Alex will be able to swap the user interface for a .NET Maui one and build an Android application for us.

If there’s time left after that, we’ll work together to fill in the gaps in the logic. But that’s not a major concern for me; my focus is to allow Alex to learn and practice the things they’ve learned so far, and to get them the experience of working on an app.