Stop Agonising Over Tiny Details

I recently started a new side project using React and – having not used React in anger before – wanted to get off on the right foot.

And by “on the right foot” I apparently decided that I meant “with the perfect folder structure for my code”.

Obviously we can all agree that folder structure is the most important predictor of code quality  (<sarcasm/>) so I spent hours agonising over whether to separate  components from screens or whether to group all actions together in an actions folder and a hundred other basically-irrelevant details. I read blog posts. I tried template project generators. I poured over a huge number of “sample” GitHub repos (every one different, of course).

To reiterate: this was for a new, greenfield side project. I spent hours of my limited time worrying about where to put all the code instead of…writing any of that code!

facepalm

Hence this post. This post sits here as a reminder to myself to STOP AGONISING OVER UNIMPORTANT THINGS.

And you know what? I changed the entire structure after a week anyway.

Advertisements

Finding Freedom in “JavaScript Fatigue”

A lot of people have spoken about “JavaScript fatigue”: the idea that there are so many new frameworks, tools and ideas available to the average JavaScript developer that it’s impossible to keep up. I thought I’d add my opinion.

When I started learning JavaScript it used to be that I would try to keep up with everything. I suspect now that I just didn’t know how much was out there, but it really felt like that was an acheivable target. I would make a real effort to not only read up on new frameworks & libraries but to try them out: maybe a quick tutorial, maybe a few introductory posts, maybe even a small project.

Now, things have changed and it is obvious to most of us that there is no way you can invest that much time in every new thing that comes out.

For me, this is not a bad thing. In fact, I find it pretty liberating.

The whole situation reminds me a little bit of when I first joined Twitter. I was following maybe 20 people and I would make a real effort to read every single tweet. Ridiculous, right? But still I tried. Then I started following more people and then more people and with every extra piece of content it became less and less realistic to get through everything.

So I let go. I had to.

I couldn’t keep up with everything so I stopped trying to do the impossible and learned to let the mass of information wash over me. If something particularly catches my eye then I can read up on it but if I miss something? Who really cares?

Nowadays it feels the same with JavaScript frameworks. I may never have a chance to get my hands dirty with everything that comes out. In fact, I may never even hear of some of them. But I don’t worry any more about trying to keep up and if something really is the next big thing… well, I’m pretty sure I’ll hear about it soon enough.

mutationobserver

Cleaning up Resources using MutationObserver

Cleaning up resources?

Let’s say you’ve written a shiny new component in your favorite framework and somewhere along the way you’ve allocated a resource that cannot be automatically cleaned up by the browser.

Maybe you attached an event handler to the resize event on the window.  Maybe you passed a callback to a global object.  Whatever the case, you need to tidy up those resources at some point.

Easy enough, right?  Put a dispose method on our object to clean up it’s leftovers and make sure it’s called before the object is discarded.

Problem solved?

Problem not quite solved

What if, for whatever reason, your component doesn’t have control over the parent?  You could trust that the user will do the right thing and call dispose for you but you can’t guarantee it.

As an alternative, can we automatically clean up our resources as soon as our containing DOM element is removed?

Yes.  Yes we can.

Using MutationObserver

The MutationObserver API (which has pretty great browser support) lets you listen to changes made to a DOM node and react to it.  We can use it here to perform our cleanup.

When we create an instance of MutationObserver we specify a callback that gets details of changes made to the parent.  If those changes include the removal of our target element then we can call dispose.

Here we are observing the parent of our target node, not the node itself (which would not be notified if removed).  We need to specify { childList: true } as the second parameter to be notified of additions and removals of child items.

Disposing the Observer

Finally, we need to make sure that the observer itself doesn’t cause a memory leak!  The observer is connected to the parentElement which (we assume) will still be hanging around, so we need to make sure that we disconnect it as part of disposal.

With everything pulled together the final version looks like this…

Supporting SignalR Client Handlers after Connection Start

(Yes, that is a pretty specific post title but then this is a pretty specific problem…)

In general, when you create a new SignalR connection you are obliged to have already defined any of your handlers on the connection.yourHubName.client object. This allows SignalR to discover those handlers and hook them up to the incoming messages.

Problem: Multiple connection sources

This approach is fine as long as you have a single place from which you are starting your connection but what if you have 2 hubs, 2 separate client handlers…2 of everything?

They will both automatically share a SignalR connection so you can end up with a bit of a race condition where the first handler to start the connection will be the only handler registered.  Imagine the following handlers…

function MyFirstHandler() {
  //assign the handler
  $.connection.myHub1.client.method1= function() { ... };

  //start the connection
  $.connection.myHub1.connection.start();
}

function MySecondHandler() {
  //assign the handler
  $.connection.myHub2.client.method2= function() { ... };

  //start the connection
  $.connection.myHub2.connection.start();
}

//...some time later...
new MyFirstHandler()
//...and even later still...
new MySecondHandler()

By the time we create MySecondHandler we have already created the connection and so method2 is not attached and will never be invoked.

Solution: Proxy implementation

We can work around this by replacing the connection.yourHubName.client object (normally just a POJO) with something that is aware of the available server methods.  The new client then exposes stubs to which SignalR can connect before our MySecondHandler can provide the “real” handler implementations.

//before creating any handlers
$.connection.myHub1.client = new SignalRClient(['method1','otherHandler']);
$.connection.myHub2.client = new SignalRClient(['method2']);

The SignalRClient implementation has 3 requirements for each named handler:

  1. Always return a valid handler function for SignalR to bind, even if the real handler hasn’t been assigned yet
  2. If the real handler has been assigned, invoke that when the handler is invoked (with all args etc.)
  3. Allow client.myHandler = function(){} assignments for compatibility with existing code

The last requirement means that we need to use Object.defineProperty with custom getter and setter implementations.  The getter should always return a stub method; the setter should store the real handler; and the stub method should invoke the real handler (if assigned).

function SignalRClient(methods) {
	this._handlers = {};
	methods.forEach(this.registerHandler.bind(this));
}

SignalRClient.prototype.invokeHandler = function(name) {
	var handler = this._handlers[name];
	if (handler) {
		var handlerArgs = Array.prototype.slice.call(arguments, 1);
		handler.apply(this, handlerArgs);
	}
}

SignalRClient.prototype.registerHandler = function(name) {
	var getter = this.invokeHandler.bind(this, name);
	Object.defineProperty(this, name, {
		enumerable: true,
		get: function() { return getter },
		set: function (value) { this._handlers[name] = value; }.bind(this)
	});
}

Note that our defined properties must also be marked as enumerable so that the SignalR code picks up on them when it attempts to enumerate the client handler methods.

Now – provided we know the available methods up front – we can start the connection whenever we like and assign our handlers later!

library-api

Custom Operation Names with Swashbuckle 5.0

This is a post about Swashbuckle –  a .NET library that seamlessly adds Swagger support to WebAPI projects.  If you aren’t familiar with Swashbuckle then stop reading right now and go look into it – it’s awesome.

library-api

Swashbuckle has recently released version 5.0 which includes (among other things) a ridiculous array of ways to customise your generated swagger spec.

One such customisation point allows you to change the operationId (and other properties) manually against each operation once the auto-generator has done it’s thing.

Why Bother?

Good question.  For me, I decided to bother for one very specific reason: swagger-js.  This library can auto-generate a nice accessor object based on any valid swagger specification with almost no effort, whilst doing lots of useful things like handling authorization and parsing responses.

swagger-js uses the operationId property for method names and the default ones coming out of Swashbuckle weren’t really clear or consistent enough.

Injecting an Operation Filter

The means for customising operations lies with the IOperationFilter interface exposed by Swashbuckle.

public interface IOperationFilter
{
  void Apply(Operation operation, 
    SchemaRegistry schemaRegistry, 
    ApiDescription apiDescription);
}

When implemented and plugged-in (see below), the Apply method will be called for each operation located by Swashbuckle and allows you to mess around with its properties.  We have a very specific task in mind so we can create a SwaggerOperationNameFilter class for our purpose:

public class SwaggerOperationNameFilter : IOperationFilter
{
  public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
  {
    operation.operationId = "???";
  }
}

When you installed the Swashbuckle nuget package it will have created a SwaggerConfig file in your App_Start folder.  In this file you will likely have a long and well-commented explanation of all available configuration points, but to keep things simple we can insert the reference to our filter at the end:

GlobalConfiguration.Configuration
  .EnableSwagger(c =>
  {
    //...
    c.OperationFilter<SwaggerOperationNameFilter>();
  });

Getting the Name

At this point you have a lot of flexibility in how you generate the name for the operation.  The parameters passed in to the Apply method give you access to a lot of contextual information but in my case I wanted to manually specify the name of each operation using a custom attribute.

The custom attribute itself contains a single OperationId property…

[AttributeUsage(AttributeTargets.Method)]
public sealed class SwaggerOperationAttribute : Attribute
{
  public SwaggerOperationAttribute(string operationId)
  {
    this.OperationId = operationId;
  }

  public string OperationId { get; private set; }
}

…and can be dropped onto any action method as required…

[SwaggerOperation("myCustomName")]
public async Task<HttpResponseMessage> MyAction()
{
  //…
}

Once the attributes are in place we can pull the name from our filter using the ActionDescriptor

operation.operationId = apiDescription.ActionDescriptor
  .GetCustomAttributes<SwaggerOperationAttribute>()
  .Select(a => a.OperationId)
  .FirstOrDefault();

Voila!

Hiding ProxyApi Routes from Web API Help Pages

If you are using ProxyApi and you have tried out the Web API Help Pages feature then you will have noticed a bunch of duplicate routes showing up for all of your actions that look something like this:

GET /api/{proxy}/Controller/Action?foo=bar

ProxyApi needs to be certain of the Route-to-Controller/Action mapping in order to correctly generate the JavaScript proxies, and it achieves this by inserting a custom route at the start of the route table so that it will always take precedence (if matched).

Unfortunately the Web API ApiExplorer finds these routes, maps them to the action and generates a duplicate route for every action in your API!

Getting Rid of the Routes

Thankfully it is very simple to filter these out.  When you add the Web API help pages package to your project it will generate a LOT of code that builds and renders the help page content.  This gives you plenty of entry points in which you can intercept and hide the ProxyApi-specific routes.

For our purposes here we can subclass the ApiExplorer class and filter out any route that contains “{proxy}”.

public class CustomApiExplorer : ApiExplorer
{
  public CustomApiExplorer(HttpConfiguration config) : base(config)
  {}

  public override bool ShouldExploreAction(string actionVariableValue, HttpActionDescriptor actionDescriptor, IHttpRoute route)
  {
    if (route.RouteTemplate.ToLower().Contains("{proxy}"))
      return false;

    return base.ShouldExploreAction(actionVariableValue, actionDescriptor, route);
  }
}

Now we just need to plug this implementation in instead of the default…

//in your help page configuration
config.Services.Replace(typeof(IApiExplorer), new CustomApiExplorer(config));

…and we’re done!

Learn through Doing

Tell me and I forget. 

Teach me and I may remember.

Involve me and I learn

Everyone learns in their own way but I have always believed that the best way to learn anything is to try it out. Try and fail, if necessary – failing is only learning that your current approach doesn’t work, as Edison might say – but the important thing is to try.

I find this to be particularly to true with technology: new languages, new frameworks or new concepts. I can see the value in courses and tutorials but I always find that a technology only really feels familiar to me once I have used it in to do something real.

The trick, then, is to find a way of using that exciting new technology you desperately want to learn…

Use it in your Day Job

Where do you do most of your development? Exactly. So if you want to learn AwesomeNewFramework then consider whether or not it would be of use to your company: perhaps it adds something that you can’t do today, or improves on the processes you currently use.

Obviously this is not always possible. Almost all software companies will have established technologies and established products, so changing to a new framework or language is not always practical. People have to be trained, products have to be updated…it might not be worth the effort for an uncertain benefit.

So if we assume that we can’t use it at work, how can we find another project to learn with?

Have an Idea

Working on personal projects or side projects is – in my opinion – always a good idea for any developer. Doing all of your work in a single project or in a single language is a recipe for stagnation.

If you have a great idea for a project and you want to learn a new technology then it is a double benefit. By having a real-world problem to solve you will immediately be forced to look deeper into the technology than you would during any tutorial or course. If someone is walking you through a prepared problem then the information is just handed to you: you may learn how to use function X(...), but you likely won’t learn why you should use it over Z(...), what happens when you leave out the optional parameters, and why the bloody thing won’t work when you need it to!

When you are trying to solve a specific problem you almost-inevitably find a deeper understanding of the code on which it relies.

For me, side projects are always my preferred way of learning. A personal project has no existing structure to confuse or to be misunderstood; it has no limits on what it does or how it works besides those that you decide. Once complete, you – the author – know the story behind every line of code and every design choice.

The only problem is that it does rely on having an idea. Coming up with ideas that are both useful and will not take too long to create is often a sticking point, so how can we come up with real-world scenarios from which to learn without that creative spark?

Solve Someone Else’s Problem

A great way to learn is to teach someone else, and one of the many great things about the internet is that it is full of people who want to be taught!

If you are looking to improve your knowledge of a technology but you don’t have the time to take on a whole project, take a look on Stack Overflow. You’ll find a long list of other people who ask a constant stream of questions – from beginner to advanced levels – about the framework or the language you want to learn.

Some of those questions will be beyond your knowledge; some you will be able to answer immediately. In either case, try to write an answer.

It doesn’t matter if there are already answers, or if you think you might need to go and investigate for 15 minutes before you can respond: by finding a solution and then explaining that solution to someone else you will automatically be improving your own knowledge. As an added bonus, you might have helped another poor soul on their way to understanding as well!

Wrapping Up

In summary, you will always learn more by tackling real-world problems rather than hand-picked scenarios from a tutorial. Ideally you want to use your own problems, but if you don’t have access to the right kind of project just now then go help someone else with theirs!