Don’t use internal tooling, contribute to your tools.

There is a dichotomy in software engineering organizations, some only use public tooling, entirely avoiding building their owns tools. Other companies  follow the ‘Not invented here’ principle and try to only use software developed internally. 

There are two forces driving this split, first building software tooling is expensive, small companies often cannot afford to build and support internal tools. It is an expensive recurring cost that can easily get out of hand. Building 2 internal tools a year will set you on a path to supporting 20 tools 10 years from now eating huge chunks of your operations budget. 

The other force in play is that if you use public or off the shelf tooling you will encounter workflow discontinuities that are difficult to fix. Using off-the-shelf tool A with tool B might require an entire employee to bridge the gaps manually, while still be a pain for everyone involved. Decision makers at some companies think to themselves, “We can just build a tool B that works perfectly with our use case.” And that works great when you have one tool, but then when need C comes along your team  makes the same case again, “We already invested in custom tool B we can’t throw away that work, we need a new custom tool for need C”. And now your company is on the path towards building an alphabet’s worth of internal tools that aren’t useful outside of your business.

Luckily, there is a solution to this. Use Open Source tooling and when you run into a workflow problem, work with the maintainers to contribute a fix. Even in poorly managed projects extending the code to support your use case will be less costly than building an entirely new internal tool to solve the same problem. 

Previewing image uploads with stimulus.js

I’ve been working on a website with file uploads lately and after a bunch of googling put together a solution using stimulus.js instead of jQuery as not using jQuery is the thing now.

The website I’m working on allows people to upload images and then to tag them before sharing and I thought it was a bit sub-optimal to ask people to tag their images without being able to see them. 

I’m using rails so this component has two parts the javascript file and my html template file. In the html template file I have a html form created via the rails form_with helper. 

<%= form_with scope: :look, url: looks_path, local: true do |form| %>

    <%= form.label :title %><br>
    <%= form.text_field :title %>

    <%= form.text_field :tag_list, multiple:true %>

  <div data-controller="image-preview">
    <%= image_tag("preview.png",  :width => "100px", :hight => "100px", 
    data: { target: "image-preview.output" }) %>
    <div class="my-2">
      <%= form.label "Look Image" %><br>
      <%= form.file_field :image, :class => "form-control-file photo_upload", 
      data: {target: "image-preview.input", action: "image-preview#readURL" } %>

    <%= form.submit %>
  <% end %>

You can see there that my stimulus data-controller encapsulates the form file_input and an image tag. The image tag loads a “preview.png” on page load and then replaces that white square when the user uploads an image. Ideally, you may want to play with the visibility attribute instead of using a blank square. 

// Visit The Stimulus Handbook for more details 

import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "output", "input" ]

  readURL() {
    var input = this.inputTarget
    var output = this.outputTarget

    if (input.files && input.files[0]) {
      var reader = new FileReader();

      reader.onload = function () {
       output.src = reader.result



The stimulus.js controller is here. It uses two targets the “input” which is the form file field and the “output” which is the image tag we are updating with the new image. This javascript uses the FileReader ( API to read the image off of the user’s computer and display it without needing to move the image across the network. 

This ended up being pretty simple to do in stimulus.js. I like that we don’t need QuerySelectors or anything non-deterministic like that and can just reference our targets directly. I haven’t included the webpack and rails integration code, it was a little tricky, and is a topic for another blog post. 

Software is a depreciating Good

“If customers are paying for the work, presumably by the hour, then you can’t expect them to pay for weeks (or more) of work every few years just to arrive back at the same product they started with.”
– From reddit user /u/PragmaticFinance

People have the idea that because the software has the same features as it did five years ago, it still is just as ‘good’ as it was five years ago. And if we can keep running it without modifications that is a reasonable practice. Unfortunately, while it feels intuitive that is not the reality with software. 

Sorry, a software product that is built on out of date tooling is strictly inferior to software built on up-to-date tooling. It is not ‘just as good’ it is significantly worse. The out of date software has increased vulnerability to security defects. Python 2.7 doesn’t get security patches anymore, if your software is built on it and a zero day is discovered. Your software could be unoperable for weeks while engineers upgrade it to function on Python 3. 

Software that can’t be patched to address security vulnerabilities in a reasonable time frame is strictly worse than up to date software. Anyone who was evaluating a purchase of these two programs would consider the expense of making changes. 

Aside from security issues, out of date software is harder to modify. What are the banks going to do when the last Cobol programmer dies? They will have to fund Cobol bootcamps which is not going to be cheap.

What are companies that had ‘feature complete’ software that didn’t need to change in years doing now that GDPR is a thing? That software is getting dusted off and updated or entirely replaced.

Roads and tractors require constant maintenance just to keep doing the same job. Software is the same. Maintenance costs should be estimated and included in the total cost of ownership for software. 

A lot of business software just encodes business processes. It can get out of date because the world shifted and the process changed, or the world shifted and the way the process is encoded is out of date.

Each time I write one of these technical debt posts it helps me understand why Software As A Service took over in such a big way. If you needed this year’s model of tractor every year you would lease it.

Figure out how to debug everything, kill blackboxes

 Avoid blackboxes in your tech stack. It is tempting to say “oh, this piece of software is acting up, but its not our team’s responsibility its xyz team’s problem”. Or this vendor’s software is acting up, “Guess we have to take 30 minutes off while we wait for it to come back up”. Sometimes this pattern shows up in the use of 3rd party libraries. 

It is tempting to allow the resistance to figuring out another piece of software block you from making progress on your project. But letting yourself take the easy route will slow down your progress as a software engineer. A blackbox is just a piece of software you don’t understand yet. You have worked with and figured out hundreds of programs in your career. This one isn’t anything special. 

Don’t let a bug in the end to end framework prevent you from making progress. Figure out the problem, open a ticket against the team that owns it. If you can make a fix yourself. The last thing you want is to get nothing done because you were waiting for someone else to fix a problem that you could have fixed, but “didn’t have to”. 

If your team has a docker compose stack for local testing, figure out how to get it running. Fix the documentation, test your software e2e locally. 

If there is an old integration test suite that intermittently fails, don’t let those failures block your work. Fix the failures, mock the flakey dependencies, don’t just sit there and let some software waste your time because you didn’t want to put the effort into deciphering how it works. 

Working from home

I’ve been lucky enough not to be laid off yet, and have been plunged headfirst in working from home. Before this pandemic I avoided working from home because I got distracted pretty easily and found it easier to get work done in the office. I’ve typically been a high performer and like to maintain work life balance so falling behind because I worked from home is not an option. 

Now I’ve been required to work from home since early march. The first couple weeks were rough. Working in a new setting, big changes going on in the world, combined to make focus difficult. I fell behind where I wanted to be on several projects. It was all dragging me down.

Late last week, at the time of writing, I made two big changes which seem to be helping a lot. They are getting better sleep and using the Pomodoro technique to focus on work. 

To get better sleep, all I did was start closing my blinds in the evening. I live downtown, so at night there are lots of light shining into my nice large windows. The view is good, but the light degrades sleep quality. I noticed a big difference the first night and have been feeling consistently good this last week.

My version of the Pomodoro technique is to do 40minute ‘sprints’ of focused coding time. This gets me past the initial hump and doing solid work. Then I take a short break and circle back for another round of focused work. This is similar to what I would do in the office, work for a while, then chat with coworkers or go to the lunch room. Except now I just stay in my apartment and stretch or workout.

Working from home is still a bit rough. But I think I’m past the hump of adapting to it. Now I just want to optimize a few things like my monitors and getting a motorized standing desk.