Javascript: Require and Import Found Harmful

For the moment, let’s go ahead and make an assumption: automated tests (unit tests, integration tests, etc.) make code safer to write, update and change. Even if tests break, it says something about how the code was written and pulled together while running. I will address this concern in another post at a later date. Nevertheless, I am going to rely on this assumption throughout this post, so if you disagree with the initial assumption, you might be better served to drop out now.

Now that the grumpy anti-testers are gone, let’s talk, just you and I.

I don’t actually believe that require or import — from the freshly minted ES module system — are inherently bad; somewhere, someone needs to be in charge of loading stuff from the filesystem, after all. Nevertheless require and import tie us directly to the filesystem which makes our code brittle and tightly coupled. This coupling makes all of the following things harder to accomplish:

  • Module Isolation
  • Extracting Dependencies
  • Moving Files
  • Testing
  • Creating Test Doubles
  • General Project Refactoring

The Setup

Let’s take a look at an example which will probably make things clearer:

To get a sense of what we have to do to isolate this code, let’s talk about a very popular library for introducing test doubles into Node tests: Mockery. This package manipulates the node cache, inserting a module into the runtime to break dependencies for a module. Particularly worrisome is the fact that you must copy the path for your module dependencies into your test, tightening the noose and deeply seating this dependence on the actual filesystem.

When we try to test this, we either have to use Mockery to jam fakes into the node module cache or we actually have to interact directly with the external systems: the filesystem, and the external logging system. I would lean — and have leaned — toward using Mockery, but it leads us down another dangerous road: what happens if the dependencies change location? Now we are interacting with the live system whether we want to or not.

This actually happened on a project I was on. At one point all of our tests were real unit tests: i.e. they tested only the local unit we cared about, but something moved, a module changed and all of a sudden we were interacting with real databases and cloud services. Our tests slowed to a crawl and we noticed unexpected spikes on systems which should have been relatively low-load.

Mind you, this is not an indictment of test tooling. Mockery is great at what it does. Instead, the tool highlights the pitfalls built into the system. I offer an alternative question: is there a better tool we could build which breaks the localized dependence on the filesystem altogether?

It’s worthwhile to consider a couple design patterns which could lead us away from the filesystem and toward something which could fully decouple our code: Inversion of Control (of SOLID fame) and the Factory pattern.

Breaking it Down

To get a sense of how the factory pattern helps us, let’s isolate our modules and see what it looks like when we break all the pieces up.

With this refactoring, some really nice things happen: our abstractions are cleaner, our code becomes more declarative, and all of the explicit module references simply disappear. When modules no longer need to be concerned with the filesystem, everything becomes much freer regarding moving files around and decoupling concerns. Of course, it’s unclear who is actually in charge of loading the files into memory…

Whether it be in your tests or in your production code, the ideal solution would be some sort of filesystem aware module which knows what name is associated with which module. The classic name for something like this is either a Dependency Injection (DI) system or an Inversion of Control (IoC) container.

My team has been using the Dject library to manage our dependencies. Dject abstracts away all of the filesystem concerns which allows us to write code exactly how we have it above. Here’s what the configuration would look like:

Module Loading With Our Container

Now our main application file can load dependencies with a container and everything can be loosely referenced by name alone. If we only use our main module for loading core application modules, it allows us to isolate our entire application module structure!

Containers, Tests and A Better Life

Let’s have a look at what a test might look like using the same application modules. A few things will jump out. First, faking system modules becomes a trivial affair. Since everything is declared by name, we don’t have to worry about the module cache. In the same vein, any of our application internals are also easy to fake. Since we don’t have to worry about file paths and file-relative references, simply reorganizing our files doesn’t impact our tests which continue to be valid and useful. Lastly, our module entry point location is also managed externally, so we don’t have to run around updating tests if the module under test moves. Who really wants to test whether the node file module loading system works in their application tests?

Wrapping it All Up

With all of the overhead around filesystem management removed, it becomes much easier to think about what our code is doing in isolation. This means our application is far easier to manage and our tests are easier to write and maintain. Now, isn’t that really what we all want in the end?

For examples of full applications written using DI/IoC and Dject in specific, I encourage you to check out the code for JS Refactor (the application that birthed Dject in the first place) and Stubcontractor (a test helper for automatically generating fakes).

Comments Off on Javascript: Require and Import Found Harmful

Coder Joy – Exploring Joyfulness In Creating Software

A couple weeks ago, I attended Agile Open Northwest. As with every other Agile Open conference I attend there were plenty of eye-opening experiences. One experience which surprised me was actually a session I facilitated. I went in with a concept of where it would land and I was dead, flat wrong.

I anticipated my session about creating joy for coders would be small and filled primarily with technical folk who wanted to figure out how they could make their experience incrementally better while they worked daily at their company. Instead I had a large crowd of people who performed a variety of duties at their company and they all wanted to get a perspective on how to make things more joyful. This, in itself, brought me a ton of joy.

The Inspiration

Before I dive into the experiment I ran, I want to share a little background on how I arrived at the idea that there could be joy while coding. I know a lot of developers get a fair amount of joy out of creating something new. That first line of code in a fresh project can create a near euphoric experience for some developers. Later, as the code base ages, it can seem as though the joy has drained completely from the project and all that is left is drudgery and obligation to keep this project on life support.

I felt this very same thing with one of my own open source projects. I was shocked at the very notion I had started developing something which I very much wanted, only to find myself a couple years later feeling totally defeated every time I opened my editor to do a little bug fixing.

I decided I would make one last effort to combat this emotional sinkhole which used to be an exciting project for me. I went to work capturing information at the edges of my code, clarifying language which was used throughout and, ultimately, reformulating the domain language I would use to describe what I was doing. After some time and a little digital sweat, the project came back to life!

I realized I was actually more excited about my project NOW than I had been when I even started writing it in the first place. I actually was experiencing that same joy I used to experience when starting something afresh. Once I found this new dharma in code, I felt it only made sense I try to share it with my team at work. They loved the notion of joyfulness.

An Experiment In Joy

Having found this new, lasting sense of joy, I wanted to share it with the agile community. I didn’t have a deep plan, carefully constructed with layers of meaning and a precise process with which I could lead people to the promised land. I was just hoping someone would show up and be willing to share. With that in mind, here’s what my basic plan was:

  1. Drain the wound
  2. Make a Joy Wishlist
  3. Pave the Path
  4. Take Joy Back to the Team

I hoped this would be enough to get people talking about joy, what it meant and how they could claim it in their team. It seemed to pay out. Just having a list of pithy step names isn’t really enough to make sense of how to run this experiment in another environment, however. Let’s have a look at each step and what it means.

Running the experiment

Before starting the experiment, the facilitator must come in with certain assumptions and be willing to defuse any emotional outbursts that might begin to arise. It’s important to note that defusing is not simply squashing someones feelings, but accepting they have a feeling and help to reframe what might lead to how they are feeling this way.

In severe cases, the feelings that arise while experimenting might actually warrant deeper exploration before continue digging into building joy within your team. These explorations are okay, and should be welcomed since they will help people to start understanding where others on the team are coming from.

Drain The Wound

If we consider how medicine works, if someone is sick because they have a wound which has become infected, the first step to regaining health is to drain the wound in order to get the toxins out of the body. In much the same way, we will never become healthy as a team if we don’t drain the wounds which have accumulated throughout our lifetimes.

The exercise of draining the wound is simple: give people post-its, pens and a place to put everything and have them write down every last negative thing they feel about their work, the process or anything else that has them struggling with emotion coming into the experiment. It is important to discourage using names or pointing fingers since this simply spreads toxins around. We want to capture the toxic feelings and quarantine them.

The most important thing after performing this draining is to take all of the collected post-its and place it somewhere people can see it. Make sure to note: we are not ignoring the pain, we all know it is here and it has been exposed.

This is important.

If something new bubbles up during the course of the experiment, people should be welcomed to continue adding to the quarantine. It’s not off-limits to update, we are just setting all of the infection in a place where it can’t hurt us.

Sometimes wounds need more than one draining. Don’t be afraid of coming back around and doing this multiple times. Always be vigilant and identify new wounds that may be growing. Emotions can be fragile and wounds can be inflicted over time. We’re human, after all.

Make a Joy Wishlist

Everyone has things they wish they had. More time off, more support, faster builds, cleaner code, better communication, etc. Encourage people to simply write these things down. As a facilitator, you can also log ideas as people generate them. The important thing is to avoid filtering. The goal is to identify all the things which would make people happy regardless of how big, small or outlandish they are.

One important item here is, don’t log/allow anything that says stuff like “Bob needs to deliver stuff on time” or “make code suck less.” These kinds of negative statements are not things to aim for. Instead encourage people to think about what it means for code to suck less. Perhaps what Bob needs to deliver faster is support, so try to capture something like “help Bob when he feels overloaded.”

Pave the Path

Once people have come to a natural close on what their joy might look like, it’s time to start looking for ways to take action. It’s not particularly useful to identify things which could be joyful if they are little more than simply a dream never to be realized. Aim to start paving a path people can walk to approach the things which help them feel greater joy.

Once again, our goal is to seek positive actions, which means we want to limit the kind of negativity which might bubble up. The negativity is likely rooted in the toxins we purged at the beginning, so help people to reframe into something positive.

In the session at Agile Open, someone mentioned they believed developers are lazy. Instead of dwelling on it or letting it become a toxin in the middle of our joy seeking, I tried to encourage them to understand the developers and their position, while also pointing out these same developers might not understand that person’s position either. From here, we can see joy might take the form of more open, honest communication. Once we understand the tension, we can seek a problem and pose solutions.

Take Joy Back to the Team

To close the session, I encouraged people to think about ways they could take the message of joy, and what we discovered during our exploration, back to their respective teams. The goal here was not to be prescriptive. Instead each team needs to find their own joy and way to walk the path.throw them out

Within your own team there are several directions you can go from here; any of the following would be reasonable to try out:

  • Dot vote on a point of joy to focus on and develop a path toward joy
  • Pick an action at random, try it for a week and reflect on whether things were better or worse
  • Leave each person with the idea that they must travel their own path to find joy and simply leave a single rule: one person’s path cannot stomp on another’s
  • Devise your own brilliant plan on how to start moving toward joyful coding given what you’ve found

The most important part of this last bit is to ensure people feel empowered to drive toward joy on their own and together. It is up to the team to support each other and elevate the environment they are in.

Closing, Joy and My Approach

I will say, there is a fair amount of time I spend seeking joy on my own. I typically mix a bunch of different ingredients including music, time for recharge, time to vent, and poking the system until it moves in a way that feels better to me.

It’s really hard to say what might bring joy in a team or even for an individual, but I find joy often comes to me as clear communication — both in code and person to person, as a sense of directed purpose, as automation, and as opportunity to share, with others, the things which make my life a little better.

Perhaps you’ll find your team values some of these things as well. In all likelihood, your team will value things I wouldn’t have thought to include in this post; this too is completely acceptable. Unfortunately seeking joy is not a clear path with a process to force it to emerge. Joy is a lot like love, you just know it when you feel it.

Comments Off on Coder Joy – Exploring Joyfulness In Creating Software
Similar posts in Coding, General Blogging