studio status report: 2022-04

month 4 of 2022 was about the greatest weakness of Blazor and more day-job learnings

There are no more known technical blockers in the way of completing the project associated with new version of This is great news! However, the underside of this news is my discovery of the greatest weakness (to me) of Blazor: Blazor only has one thread even though WebAssembly has more.

As of seven days ago, Dan Roth is optimistic that Blazor will support multi-threading in a near-future release. This should prevent me from looking into things like BlazorWorker [GitHub].

This threading weakness makes me write Bolero code like this: (fun _ ->
    if model.YtSetIndex.IsNone && model.YtSet.IsNone then
        YouTubeMessage.CallYtIndexAndSet |> dispatch
        YouTubeMessage.OpenYtSetOverlay |> dispatch)

What this click handler is trying to say is that Blazor cannot handle playing a CSS animation, opening an overlay, and retrieve cached data near-simultaneously. Before the data is cached, model.YtSetIndex.IsNone and model.YtSet.IsNone are both true and this click handler is gambling that it will take at least one second to retrieve the data remotely. Why one second? That is the duration of my CSS animation. When I am wrong about the one-second data-retrieval floor, then Blazor innards will block the CSS animation.

day-job learning?

Yes, I have a new day-job after quitting the old one last month. Of course we all say this but for me it is true: this new job is better than the last one. It has allowed me to revisit validation which is the bread and butter of full-stack forms building. Enter FluentValidation [GitHub].

The ‘horrible’ truth about the built-in system featuring System.ComponentModel.DataAnnotations.ValidationContext [📖 docs] starts with its ObjectInstance property (which is boxed as object). this property effectively associates any Validation Results with the object they come from. This implies that there one Validation Context per validation. It follows that recursively validating child objects (or collections of child objects) is not supported.

The response to issue #1133 introduces FluentValidation [GitHub] to me as the solution to this limitation:

public class ProductValidator : AbstractValidator<Product> {
   public ProductValidator() {
      RuleForEach(x => x.ProductVariants).SetValidator(new ProductVariantValidator());

public class ProductVariantValidator : AbstractValidator<ProductVariant> {
  public ProductVariantValidator() {
     RuleForEach(x => x.Prices).SetValidator(new PriceValidator());

public class PriceValidator : AbstractValidator<Price> {
   public PriceValidator() {
      RuleFor(x => x.Price).GreaterThan(0);

RuleForEach coupled with SetValidator in FluentValidation is documented.

For more background on the limitations of default .NET validation, see “Recursive Validation Using DataAnnotations.”

to avoid validation, use change tracking

I admit that I am a bit embarrassed to have taken so so long to take FluentValidation seriously which implies that I never thought about the problem of recursive validation in depth for years—what kind of day jobs was I working? (The kind of day jobs with too much legacy code with legacy problems in the way of working something relatively new.)

After FluentValidation is taken seriously, my next serious move is toward Compare-Net-Objects [GitHub]. How did I stay alive so long without this thing! When validation is considered a performance issue then it can be avoided by verifying that the object is unchanged when compared to its last-saved version. Compare-Net-Objects works well in this scenario and is my lightweight answer to a full-blown change tracking system like the one I have enjoyed in years past in Entity Framework.

selected month 04 Studio notes

Change-tracking in .NET

  • The IChangeTracking Component Model interface is foundational in .NET [📖 docs].
  • IRevertibleChangeTracking extends IChangeTracking by adding support for rolling back the changes [📖 docs].
  • Entity Framework has its own change tracking subsystem.
  • TrackerDog [GitHub] depends on declaring all public properties as virtual [📖 docs]. This project has not been touched for years.
  • ChangeTracking [GitHub] also depends on public virtual properties but has been touched more recently than TrackerDog.
  • PropertyChanged.Fody [GitHub] depends on implementing INotifyPropertyChanged.
  • PropertyChanging.Fody [GitHub] depends on implementing INotifyPropertyChanging [📖 docs].
  • TrackChange [GitHub] is built on top of Fody and only requires the attribute, [Tracking].

You can also implement a change tracker to keep track of everything for more complex scenarios. The change tracker might have a list of the changes—listing property names, values, and timestamps as needed—internally. You can than query this list for the information you need. Think of something like the [Event Sourcing] pattern.

I will need AutoMapper primarily for tests

AutoMapper supports cloning:

Bogus is a simple fake data generator for .NET

Bogus GitHub is unit-test companion for shipping code with validation logic. By the way, I did have the day-job opportunity to compare Bogus to AutoFixture. The only advantage AutoFixture has over Bogus is its ability to generate random data by default. Bogus requires a rules engine to generate anything but this is better out of the box than what AutoFixture presents because the rules work well with validation unit tests.

Once AutoBogus [GitHub] is coupled with Bogus then I am pretty much set.

roll up of my .NET forms-building tools

When the day-job folks turn down some third-party vertical like, then I will immediately need these:

package name Nuget URI GitHub URI

sketching out a development schedule (revision 20)

The schedule of the month:

  • complete project associated with new version of 📜🚜🔨
  • generate Publication indices from LiteDB for Songhay.Publications.KinteSpace
  • use the learnings of previous work in Bolero to upgrade and re-release the kinté space 🚀
  • convert Day Path Blog and to HTTPs by default 🔐