10th week of 2021

Published on

TypeScript exercises and learnings, checking leap years in JavaScript, cool NuGet (C#) packages.

Table of contents

👨‍💼 Work

Nothing – I was on vacation for the whole week! 😊

👨‍🚀 Personal

TypeScript exercises on Exercism

I did a bunch of TypeScript exercises on Exercism. Here's their pitch:

Level up your programming skills with 3,450 exercises across 52 languages, and insightful discussion with our dedicated team of welcoming mentors. Exercism is 100% free forever.

Each exercise comes with a bunch of unit tests that you have to make pass by creating a correct implementation. So kinda like TDD (test-driven development).

I like that after submitting your own solution, you can view, comment and star solutions submitted by others. This way you can see various approaches to the same problem and hopefully even learn new tricks.

So far I have only done "easy" and "medium" exercises, which have been rather easy. There are also "hard" exercises.

I did two exercises with my brother Hannes. I was the driver and he was the navigator. I used the excellent Screen software for screen sharing. It was a nice experience; I'd like to do more pair programming in the future.

At some point I'd like to try Exercism's C# and Clojure tracks as well. And maybe even some other tracks!

👨‍🎓 Learnings

JavaScript: check if year is a leap year (in a cool way)

Colin DeCarlo tweeted a cool way to check if a given year is a leap year (code by JleCoRyl3):

function isLearYear(year) {
  return new Date(year, 1, 29).getDate() === 29
}

Quite clever! Though a bit confusing at first because months are 0-indexed. Maybe a code comment would be in order.

The tweet is what inspired me to start doing TypeScript exercises on Exercism.

TypeScript: turning constructor parameters into class properties (= parameter properties)

TypeScript docs' definition of Parameter Properties reads like so:

TypeScript offers special syntax for turning a constructor parameter into a class property with the same name and value. These are called parameter properties and are created by prefixing a constructor argument with one of the visibility modifiers public, private, protected, or readonly.

These two classes are effectively identical:

// Parameter properties
class Foo {
  constructor(
    public readonly x: number,
    protected y: number,
    private z: number
  ) {}
}

// Ordinary class properties
class Bar {
  public readonly x: number
  protected y: number
  private z: number

  constructor(x: number, y: number, z: number) {
    this.x = x
    this.y = y
    this.z = z
  }
}

I like that parameter properties reduce verbosity. But they are potentially confusing if they are mixed with ordinary class properties – it might be hard to see at a glance all the properties that the class has.

🕵️‍♂️ Cool stuff

C#: More readable unit test assertions with Fluent Assertions

Nick Chapsas's video on the Fluent Assertions package made me want to start using the package at work. Example from the video (_sut = system under test):

// Before
Assert.Equal(expected, result);
Assert.StartsWith("The result is: ", _sut.Text);
Assert.EndsWith(result.ToString(), _sut.Text);

// After
result.Should().Be(expected);
_sut.Text.Should().StartWith("The result is: ");
_sut.Text.Should().EndWith(result.ToString());

So much better. Reads like English.

Another benefit is that the messages from failed assertions are more detailed.

C#: Cleaner mocking with NSubstitute

I have previously used Moq to do mocking in unit tests.

Nick Chapsas's video on the NSubstitute package convinced me that NSubstitute would be nicer. Example from the video:

private readonly CustomerService _sut;
private readonly ICustomerRepository _customerRepository = Substitute.For<ICustomerRepository>();
private readonly ILoggingService _logger = Substitute.For<ILoggingService>();

public CustomerServiceTests()
{
    _sut = new CustomerService(_customerRepository, _logger);
}

[Fact]
public async Task GetByIdAsync_ShouldReturnCustomer_WhenCustomerExists()
{
    // ...

    // Mock implementation
    _customerRepository.GetByIdAsync(customerId).Returns(customerDto);

    // ...
}

Compare with the same code using Moq – taken from another video by Nick on the Moq package:

private readonly CustomerService _sut;
private readonly ICustomerRepository _customerRepositoryMock = new Mock<ICustomerRepository>();
private readonly ILoggingService _loggerMock = new Mock<ILoggingService>();

public CustomerServiceTests()
{
    _sut = new CustomerService(_customerRepositoryMock.Object, _loggerMock.Object);
}

[Fact]
public async Task GetByIdAsync_ShouldReturnCustomer_WhenCustomerExists()
{
    // ...

    // Mock implementation
    _customerRepositoryMock.Setup(x => x.GetByIdAsync(customerId))
        .ReturnsAsync(customerDto);

    // ...
}

When using NSubstitute, there's no need to use .Object in various places, and creating mock implementations is more straightforward.

💁‍♂️ More Weekly log entries

Next week: 11th week of 2021

Previous week: 9th week of 2021