When Not to Test Code?

I know. I know. Settle down.

No, I’m not advocating you should ignore writing tests. I’m simply saying there is a time and a place for everything and, if you want to actually ship a product, instead of just talking about shipping a product, you need to know when to execute. And, that includes the question of when to add tests.

This conversation came up when talking to a non-technical project manager this morning. So, my apologies if it’s written in that voice.

Also, this is my opinion. At the time of writing, I’ve been getting paid to write code for … wait for it… 40 years … yes forty years. And, during that time, I’ve been either the sole developer or a primary developer in many successful software products. So, I know a thing or three about this stuff. But, even with all of that, I am not saying this is the answer. It is simply my opinion.

What is a test?

An “automated test” is a set of rules and logic crafted by the developer to ensure their software item does not break in the future. These tests are automatically run and return a “pass” or “fail” result based on the rules the developer crafted. They can be very useful but are a very slippery slope. Here’s why…

Test-Driven-Development (Don’t let people do this… period.)

About 10-15 years ago someone came up with the idea of writing a massive amount of test rules (usually in lieu of having solid architecture documents) and then forcing their team to write code to satisfy those rules. The general concept is that your coding tasks were considered “complete” once all of your tests passed. The failure people rarely discussed is you generally had so many tests, and so much specialized code written to run those tests, that your development time took twice as long. What’s more, is now your developers had to become proficient in both the application’s logic and the logic within the tests. Sadly, every so often new developers will discover this technique and advocate for it without really knowing what they’re in store for.


There’s always a coding task that nobody wants to touch. It may be incredibly boring or too much of a “brain burner” to be excited about. Just like someone pushing their morning workout to some imaginary “sweet spot” after work, developers sometimes lie to themselves about the importance of working on tests in lieu of actually getting work done. And, just like pushing that morning fitness routine, this type of decision-making is seldom intentional.

Premature Test-ification

Generally speaking, any software module or application has three phases: discovery & planning, development, and maintenance. Even if they are actively coding, the majority of that time is usually spent upfront in the discovery & planning stage. This may include learning how to work with an upstream API, flushing out actual source code patterns for the team to use, or testing a concept they think may work. The real development… the meaningful development… the permanent code doesn’t actually start to be written until all of those boxes are ticked. And, until that moment, the codebase is a bit of a “moving target.” Any tests written during these phases are basically disposable since there is a massive chance they will no longer be correct and will need to be rewritten. Essentially, they are what is considered “throwaway” code at that point.

Anti-Patterns / Lack of Standards

One of the factors that annoy most developers is having to take over someone else’s code which is drastically different from their own. Part of the benefit of using tests is to help enforce coding languages, standards, and styles. Unfortunately, going back to the “premature testification” concept, in many cases those differences are acceptable and even encouraged. Startup endeavors, new development teams, and brand new software endeavors are all perfect examples of this. More often than not, in those scenarios, the primary focus is delivering that first prototype or initial product. Additionally, in those environments, you usually have a mix of skillsets. And, while that mix of skillsets will normalize over time, since those scenarios generally offer little opportunity for downtime as it is, increasing the team burden by trying to normalize disconnected skillsets often leads to a dramatic decrease in productivity or, even worse, increases the error rate of a product.

Where do tests fit in the source code?

In general, the three common types of tests are meant to SEAL a codebase, help guarantee binary compatibility between components, and protect the product from unintended code changes. More specifically…

Unit Tests

Every software product is made up of a larger number of smaller “modules” or “components” that work together to accomplish a larger task. For example, your email application probably has a “Contact” component for collecting info on people you send messages to. That Contact component would then have an “Address” component for storing the person’s mailing address. And, that Address component might have a “Postal Code” component to handle the validation of the various postal code formats around the world. Once they’re complete, each of those smaller components / modules generally have their own smaller set of tests that only test their tiny chunk of logic.

UI Tests

This one’s usually the most complex and ambiguous type of test to complete. Should a software solution have a user interface of any kind, regardless of whether it’s web-based or installed on a user’s workstation, it is common to “seal” the user interface project with a set of UI tests. These tests generally use a “headless” mechanism that quietly launches the user interface and programmatically mimics the actions a user would normally perform. From clicking buttons to scrolling to typing in text boxes, anything a user would do, the test mechanism performs those steps and reports back if the expected outcome is the actual outcome.

End-To-End Tests (Integration Testing)

One of the final types of tests is an overreaching test meant to ensure that each of the pieces meant to work together is actually capable of interacting as expected. For example, the act of a user clicking on part of the user interface probably sends data to a server and, more than likely, that server probably talks to other servers. An end-to-end test is meant to ensure events taking place on one end of the technology stack cause that chain of other events to take place properly.

So when should tests be added?

In short, the initial addition of tests should proceed when all of the following are true:

a. Design and prototyping stages are 100% complete for the module, component, or feature in question. Remember, tests are meant to ensure binary compatibility as the codebase matures;

b. Your team is fluent in the proposed testing library or technology. Give them time to ramp up and prove their skills if they are not; and,

c. The project’s lifecycle is comfortable enough, and deadlines are far enough away, so the act of adding tests to not jeopardize the project.

Go ahead. Flame me.

I get it. You’ve read this and you’re pissed. That’s cool. Again, it’s just an opinion. I’m not saying I’m right or that I know everything. All I know is that this logic has served me well in the past four decades of professional software development. Take it or leave it.

Feel free to comment if you have questions or think I’m a nut job.


Remote Until COVID?


Those three words are a joke. Unfortunately, I am still constantly bombarded by recruiters trying to use the “pandemic” as an excuse to shoehorn candidates into positions they wouldn’t normally take. It’s so much of a pain that I actually set up an autoresponder to direct those incoming recruiters to a dedicated domain I setup:

Part of the job search for most people is asking yourself if you want to tackle that morning commute. Why would you take a position not knowing when or where you would be going into the office?

And forget the commute. What about the office environment in general? Imagine the worst possible office conditions you can dream up. Now, while I doubt any office would be as bad as that, in theory, it very well could be. So, why would you agree to work in an office you have never seen before?

And what about the wacko politicians making vaccine mandates and laws on the fly? How do you know what hoop you will have to jump through next or when?

In short, I don’t ever see myself going back to the office. This COVID thing is not going away anytime soon. There is no way I would even discuss a position with may involve an office anytime in the next decade.

I need to do my best in a position. That means focusing and not worrying about random variables I cannot control.


Change is Good!

For the past few years, I’ve been using Gatsby as the main tech behind several of my blogs. I love the fact that I can edit simple Markdown and my site is magically updated on the server with a fresh React-based static website. Unfortunately, as cool as the end result may be, it’s far too complex and cumbersome for the end result. What’s worse is that, even with the complex back-end tooling in place and functioning flawlessly, the act of posting new content is far more tedious than what it needs to be. The end result is fewer updates and an eventually stale and boring site.

Tedious Setup

Let us break down the tech stack allowing Gatsby to appear magical…

Git (AWS CodeCommit)

Once you have the local tooling setup for your site to build, it needs to be pushed up to a code repo. Since most of what I do online is with AWS, this means sending it to CodeCommit. From a developer’s perspective, the act of pushing it up is trivial. However, what is not trivial is the fact that you end using cracking open your IDE or a local text editor to make said edits. Even if I used Cloud9 or some type of online editor, it’s still an editor and still means working with text files that need to be pulled down, edited, and committed. And, while, yes, I could stick my public content in a public Github repo, and edit it online, I’m still editing code directly in the source repo. Trust me, after that “new code smell” wears off, this process is more than annoying. With WordPress, on the other hand, I have a myriad of options… a web-based text editor with a draft mode, the ability to send an email to WordPress and have it converted to a post, etc. Of course, all of these options are non-destructive.

CI/CD (AWS CodePipleline)

For the Gatsby content to be compiled and pushed to the public web host you need to stand up some type of CI/CD process. My choice was AWS Code Pipeline, of course. And, yeah, it’s something we regularly do as developers but… dude… this is a blog! Even if I spend an hour or two standing up a new pipeline, it’s time I don’t have to spend with a CMS engine. Oh, and let us not overlook the fact that AWS charges per pipeline so there’s an extra cost involved as well. With WordPress, your data is sitting in a database, or on the drive, and is rendered on the fly when it is viewed.

Web Host (AWS Cloud Front)

Okay, I know what you’re saying. “It doesn’t matter what technology you use. You will need a host.” I’m not disputing that. And, I absolutely love AWS and Cloud Front. I’ll use them forever on projects. However, the amount of work required for using Cloud Front is simply not worth it for a personal blog. First, your domains need to be in Route 53. Next, you need to use Certificate Manager to request your certs for all of the names you will use on your blog. And then there is the configuration needed for Cloud Front, its regions, is origin rules, etc., etc., etc. Oh, and once Cloud Front is ready, you’ll need to return to Code Pipeline and Route 53 to connect all of the services. For a WordPress site you can … well … there are countless easier options. From performing a one-click deploy from AWS Marketplace, to setting up a LEMP stack on an EC2 instance, to Digital Ocean, WordPress.Com, or the other million hosts out there, almost every one of them will have you up and running in minutes without having to know anything about what’s happening under the hood.

LEMP Stack

Now, I’m not here to bash AWS or sing the praises of WordPress. This post was only ever meant to explain why the site is changing and apologize for any missing content while I swing it all over from Cloud Front. However, what I would like to offer are a few links to some helpful articles that make standing up WordPress (even multiple instances on the same box) incredibly easy. I snipped these and pulled them into Evernote as soon as I found them. And, they are what I use whenever I need to stand up a simple blog in a non-critical environment:

How to Install LEMP Stack on Ubuntu 20.04 Server/Desktop

How to Install phpMyAdmin with Nginx (LEMP) on Ubuntu 20.04 LTS

Install WordPress on Ubuntu 20.04 with Nginx, MariaDB, PHP7.4 (LEMP)l,”

Business Life Programming

Software As A Career

If you’re not in computers for a living in 2021, you’re nuts. It’s fun. It will improve your life (if you let it). And, it’s pretty dang recession proof. I’ve repeated these words countless times over the years and, in some of those questions, am often asked how to get started. So, I figured I’d sit down and write a quick "how to" page to help the people I care about tap into this world.

Step 1: Use Technology Daily
As generic or corny as it may sound, the world of computers is not something you can simply do or be in. It needs to be a part of your life. Those of us who are any good actually enjoy using technology and naturally make it part of our lives. We don’t need to decide or push ourselves to use technology. It’s just part of us and what we enjoy. Now, while I know there are many people out there who are intimidated by technology. Being intimidated is not the same as not enjoying it. You just need to find that hook… that part you actually do enjoy. Once you realize how common the various concepts are, from one widget to the next, more than likely, technology will become an intimate part of your world as well.

So, why is this first step so important? Simply put, the more you enjoy something the easier it will be… the more naturally you will gravitate to it. For example, as you use different cell phones, from different manufacturers, you will begin to notice similarities. As you move from cell phones to smart devices you will notice how similar those two worlds are. Tablets and laptops expand those device abilities even further. My point is that all of these devices basically work the same way. The more use use different devices, on a regular basis, the more organic your understanding about how they function will become. This is what makes technology "second nature" for many of us.

Computer Parts

Step 2: Build A Computer
Many of us these days just buy the cutest or shiniest laptop and call it a day. However, buying a prebuilt machine prevents you from knowing anything about what’s inside of the box. This is the same as buying a car without knowing how an engine works. And while that ignorance might be fine with your vehicle, you are probably not wanting to earn an income from your vehicle.

PCs for Dummies

Step 3: Read A Book
Let’s face it, there’s a reason book stores don’t exist anymore. Nobody reads. I know I would rather watch a video than spend 10 times as long reading a book on the same topic. However, in this case, there is one book I cannot recommend you read enough… PCs for Dummies! Don’t worry. It has lots of jokes, big fonts, and pictures. More importantly, it also has foundational information that most people skip over when they are first getting started in computers. This foundational knowledge is critical if you want to actually be good at what you are about to undertake.

Celel Center

Step 4: Take A Job in Technical Support
Have you ever called "tech support" and had someone reset your password or help you figure out how to make your printer work? That kid who answered the phone is referred to as "first line" or "first level" and is one step above "clueless"… just like you are at this point. Chances are he helped his mom install her cable modem once or twice before getting this job. Well, this kid need to become your pal… your co-worker. After your brain is overloaded with basics of making your computer work, you will have just enough knowledge to understand the terminology and help other clueless people fumble their way through logging into some company web site somewhere. So, hop onto one of the job boards (Monster, Indeed, Career Builder, etc.) and look for a job in a call center as a "First Level Technical Support Agent" (or similar pee-on title).

But, Fred, I don’t know enough to teach someone! Yes, you do. First-level call center jobs assume you’re clueless and are setup to teach you how to use their in-house software or system. Most of the time they will give you a script so you don’t need to worry about "winging it." The biggest perk is that they are filled with countless pre-pubescent know-it-all teenagers who are all too happy to show you what they know.

Support Level 1

Support Level 2

Support Level 3

Support Manager

Step 5: Start Writing Code … ANY CODE!
There’s no correct time to start building software. You just need to do it. By tackling the steps in the order outlined here, by this point you should be in an office environment, have regular access to a computer, have a few of them at home, and have the foundation you need to get started. You will have also been in the computer world long enough to know what a "language" is and have a inkling of what is being used in your world. For example, you may be in a company that uses Microsoft Excel or Access in their daily workflow. You may have a club or interest that needs a web site. Or, you may want to start a blog. The bottom line is that, by this point, you will probably find a need for something basic that needs to be created. You don’t have to quit your tech support job. Just spend some time after hours, at lunch, or on the weekends creating something from scratch. It may sound a bit generic, but, by the time you get to this step, you absolutely will know the difference between these pieces and have some idea of what you want to create. The key word here: create!

Possible Detour: Network Administrator
One tempting fork in the road, after your put in a year or two at the call center, is working with the actual hardware or networking gear. This is definitely a small detour I encourage to anyone who really wants to pursue any career in computers or software. In the same way that building a computer helped you understand how it works, working directly with many computers, in a network setting, or making them talk to each other, is a great way of learning how they communicate and gaining an understanding of what these beautiful boxes can do when they start communicating with each other. Or, even better, if you’re in a corporate setting, you will probably be able to land a job helping users face-to-face with their hardware. So, after your time in the call center, consider spending a year or two as a Network Administrator. You will gain a certain amount of empathy for end users here and become very familiar with concepts like "single points of failure" or what happens when companies decide to implement policies poorly.

Network Admin Level 1

Network Admin Level 2

Network Admin Level 3

Network Admin Level 4

Network Admin Level 5

Possible Direction: Network Engineer
There are two basic "forks in the road" when it comes to more senior paths in computers. For now, just think of them as "hardware vs software". Hardware geeks can make a ton of money working with the actual devices that make computers and networks talk to each other. This is a natural path if you find yourself enjoying the "Network Administrator" role we talked about in the last section. It can be a great living for someone who enjoys problem solving or working closely with the hardware itself. I spent time in this world and worked for some really cool companies… Sprint, Nextel, AT&T, several banks, a semiconductor company, etc… and am grateful for the time I spent "under the hood." Having a solid understanding of this end of the spectrum has really helped me over the years. Many software developers just know how to make the graphics on this computer screen do something without really understanding what’s happening behind the scenes. If you have both, then you’re golden.

Network Engineer Level 1

Network Engineer Level 2

Network Engineer Level 3

Network Engineer Level 4

Network Engineer Level 5

Step 6: Boot Camp
At this point you either want to stay in networking, making computers work together, or you want to come hang out with us cool kids actually creating something. Neither choice is correct. At this point we need to start building on your foundational knowledge and get you some education! Countless online and physical companies exist that will take you though a "boot camp" level course and teach you the basics of programming. These generally take a few months to complete and will give you a massive amount of knowledge in a very short amount of time. These are good for folks that have the ability to work and attend semi formal training sessions. Another avenue are online companies (Pluralsight, Cloud Guru, etc.) which offer self paced video tutorials that you follow along with and get your feet wet in developing software. Regardless of which you choose, these courses will teach you how to use the tools of the trade. The best part is that you will end up creating a few applications and, along the way, gain an understanding of how they work internally.

Step 7: Support Developer
Remember that tech support position you had a year or so ago? Well, it’s time to get another one. However, this time, you’ll be looking for bugs in software that some team of software developers created. Since software developers generally love creating new apps, and since fixing bugs in their older apps would not nearly be as fun or exciting, they need someone like you to dig through lines of software code (known as "syntax") and find the cause of their bugs. Basically, you’ll get paid to break things or figure out why they are broken. And, while this is technically another "first line" job, just like the tech support gig, it’s several steps up from that other role. Plus, now you’re actually part of a team helping create software!

Support Developer

Step 8 & Beyond: Software Developer
By this point you’ve gone from tinkering to actually becoming part of a team responsible for creating software. After spending some time in a Support Developer role, you will eventually be asked to create something knew. You’ve clearly seen what screw ups were made to cause problems. And, so, you know what not to do as you create new applications. The bottom line is that you will continue to progress from the Support role as your skills develop. As time goes on, people will consider you the more "senior" person with a certain skill or technology. You’ll be on autopilot by now.

Developer Level 1

Developer Level 2

Developer Level 3

Developer Level 4

Developer Level 5

Developer Level 6


2021 Indian Scout Bobber ABS

Welp… it happened again. I fell in love with a bike. This happened once before, in 2007, when I sat on my GSXR-1000 for the first time …

2007 GSXR-1000

Back in ’07 I had zero interest in buying my "Gixxer". Originally, I had stopped by a Harley dealer to grab a V-Rod. However, Glenda and I were ignored in the showroom and walked out. It felt as if we did not "fit in" with the "good ole boys" who were hanging out pretending to be salesmen. We stopped by a dealer in Longwood, Florida, on our way to lunch and there, where, perched on top of a display in the center of the showroom, was the fastest production bike ever made (at that point). One of the sales guys offered to set it up for me without any strings attached (added a dog bone, dropped it an inch, etc.). We came back from lunch and I ended up writing a check on the spot. It fit like a glove!

Fast forward to 2020 and I’m just not into the aggressive riding position any longer. Plus, once we sold our other bikes, there was no longer an opportunity for Glenda and me to ride together. So, for the past few years, she’s just sat in the garage. I started looking at cruisers again and this time stumbled across the 2020 Fat Boy 114. It’s not often Harley makes a bike I like the looks of and their 30th anniversary model caught my eye. Now that I had a bike in mind, as any self-respecting geek would do, I set out to the interwebs to dig into a few reviews. It was at that moment everything began to change.

2020 Fat Boy 114

Search after search resulted with the same type of video showing up in my results… "10 Cruisers Better Than Harley"… "Harley: Twice the Price for Half the Horsepower"… and, finally, "Harley vs Indian". In fact, everywhere I looked, there were loads of videos comparing Indian to Harley. Granted, I had no idea why, however there were too many results to not click on one of them. Without repeating the gobs of reviews out there, the comparisons basically came down to Harley owners sticking with tradition rather than venturing into technology. And, ironically, that V-Rod I was looking at back in ’07 actually became one of the most hated bikes within the Harley world because of it.

As a full disclaimer there was another facet that kept me looking at these reviews. Early on in my search I was pre-approved for financing on any Harley I wanted. They were offering to basically give me a bike without any money down and with an interest rate under 1%. However, this fact didn’t mean jack to any of the dealers I called. Even after I had taken the time to locate the model I wanted, not one of them was actually willing to do any work to ship it from the dealer who had it. I even called dealers owned by the same parent company. And, while they all said they would call me back with dates and details, not a single one of them actually did.

What came next is simply not fair… not fair to Harley, that is. Long story short, I called Indian of Springfield and talked to "AA". The experience I had from that point forward set the stage for the most enjoyable and painless purchase ever. AA basically grew up on Indian bikes, loves the brand, loves the dealership and owner, and was all too happy to share her years of experience. I won’t go into a ton of detail here about the dealership, but, man, it was almost painful to leave. Every person I spoke to was so helpful and pleasant that I thought they were a family-owned business. I actually found out weeks later that the incredibly low-key guy who delivered the bike to me was actually the owner, Dennis! Granted, by the time I learned that bit of info, I had already bought my bike weeks before, however it just proved how genuine the people were.

BTW: Here’s a quick video of AA:

Sorry. I know I started this post to write about the bike. However, the whole experience has simply been so positive (and completely different from the Harley world) that I can’t stop talking about it.

The bike I went with was a 2021 Indian Scout Bobber ABS. At first I was a bit worried about the lean angle and dragging the pegs. I was also a bit nervous if I would hate a two-cylinder engine (that’s right … half of the engine in my GSXR-1000). However, by the time I was home I was in love. It’s now been just over two weeks and now my only worry is if it is going to be warm enough to ride.

Bobber at Shop

For me, and where I’m at in my life, this bike is perfect… to the point where, yeah, it’s like falling in love with a machine. Probably not a surprise, but the ride feels like a cross between a cruiser and a sport bike. It still corners and handles the way a smaller or tighter bike would feel. However, the riding position is more relaxed… almost proper… compared to the Gixxer. For me, the biggest difference was hitting the highway for the first time. Even at a modest 60 MPH, the combination of not having a fairing and maintaining a more upright body position causes you to feel the wind impact and the front forks a bit more. You’re not exactly cutting through the wind as much as you are handling it. It’s not a bad feeling at all… just different. For me, this bike is fun because it feels like it belongs on the back roads here in Connecticut. Unlike the feeling of opening up a crotch rocket on the highway, and trying not to bury your tach in the red, this one is more about enjoying the road and world around you while still having fun in the curves. It’s actually a quite intoxicating experience.

Bikes in Bridle

The rides on these two bikes are so different that I can make a valid argument to hang onto both of them. Originally, I saw Glenda has becoming one with the GSXR. However, I’m loving the Bobber so much that I would not be opposed to switching it out for a second Indian come the spring. I’m not sure where we’ll be but, regardless, I’m certain we would be buying from Indian of Springfield.

Business Hobbies Life

FAQ – Development

Why do I write code? That question, and many others, answered here …

How long have you been programming?
Can’t believe I’m about to say this, but going on 39 years (38 professionally). This all started back in 1981 because of a pompous jerk who insulted my dad. One of my older sisters visited with her boyfriend. While getting to know our dad, he mentioned how my father "would not understand" how great it was that he sat in an air-conditioned office all day "programming." That Christmas, my parents gave me a Heathkit "kit" computer and I was on my way. I learned how to solder, build the computer, and started learning how to program. Admittedly, at first I wasn’t actually competing with the guy. However, a year or so later, he ended up buying a simple video game from me so he could resell it. The lil’ shopping spree which followed had me hooked. The thought of someone giving me money for something I actually enjoyed doing was a high. The fact that this egotistical oaf paid for it was simply icing on the cake.

So, why are you still writing code?
That "high" I mentioned above has never gone away. The act of breathing life into an idea, and seeing someone actually enjoy using it, will never get old. Some guys come home from work and turn a wrench as a hobby. Fortunately, I found a way to make a living with my hobby. There’s also something thrilling about brainstorming and building something with a team. In keeping with the "turning wrenches" analogy, it’s like working with a team to build a race car. Everyone has ideas and visions. There’s no real "winning" or "losing" within the team. You may be changing a tire one day or working on aerodynamics the next. That collaborate effort… the occasional pressures and accomplishments… it’s an amazing feeling almost every day.

What types of applications do you create?
Although they’re not as glamorous as an "Angry Birds" game, I prefer creating line-of-business ("LOB") solutions. In short, these are the culmination of creating multiple "apps," services, and databases to provide a much more significant "system" or "solution". This type of effort also involves the creation of many utilities and processes (both manual and automated). I find these most enjoyable because they are directly responsible for allowing a company or organization to either overcome a hurdle or improve their business overall. They’re also chock full of countless opportunities for accomplishments. For example, delivering an improved user interface often means actually improving the way a group of people perform their job. Seeing the happiness in an end user’s face is incredibly rewarding. Even the unseen widgets one must create along the way are rewarding. Every time you implement a piece you are able to improve a process, increase reliability, decrease operating costs, or in some other way make the overall solution better. In short, this type of solution is almost a never-ending path of challenges and accomplishments. And, above all, the amount you learn about the company or industry, along the way, is invigorating. It’s almost like you’re watching a glowing "power meter" increase above your head.

Do you prefer back-end or front-end?
Both. While I realize there are people who mainly want to write pretty UI’s and others who prefer never looking at anything but text, I don’t think I would truly be happy in a position where I must always do one or the other. Even if my initial responsibility on a team is one end or the other, there are countless leaning opportunities when you jump into whatever that other area may be. For example, digging into the data helps you understand the "bigger picture" and business needs. This translates to being able ensure the middle layers work more intelligently and that usually allows you to trim out what the front end needs to worry about. Likewise, working with the front-end, and listening to feedback from users, allows you to optimize the user experience and build an app that people will actually enjoy using.

What is your favorite role in a team?
There’s an old saying, "Lead, follow, or get out of the way." Let’s face it, I’ve been writing code longer than many of my teammates have been alive. I’ve run teams, architected products, built and sold companies, invented patented technologies, etc., etc., etc. However, none of those past experiences mean I am all-knowing or that I’m the greatest whatever. Every team is different. Every person is different. And, let’s face it, the technologies we used when I started are long gone. Heck, the technologies we used five years ago are virtually dead. What my 40’ish years have given me are experiences in a wide breadth of technologies, concepts, tools, and lessons learned. It’s also given me a solid belief that the best role for any person is one where they are both capable and needed. If the team needs me to act as a BA, work with the business, and write documents, then be it. If we need someone to analyze CPU and memory footprints to squeeze the last drop of performance out of a process or database query, then I will happily be there. Like I said, just having a seat at the table with your team, and participating in breathing life into that overall solution, is such a rewarding experience that the role or title itself if irrelevant.

How do you remain current?
After being asked this one a few times, I started using it when I interview people… mainly to determine what type of worker a person will be. Are they a "9 to 5’er"? Are they a geek? Or, are they just chasing a six-figure paycheck? While there are some useful "go to" sites or blogs that you may find out about when asking this question, however what I am generally looking for is how wide-reaching their resource list may be. There’s not a "correct" answer to this question. If people are genuinely in this field because they enjoy the technology, then there’s a almost a permanent "feed" of knowledge. It’s almost as natural as breathing.

Do you prefer technology X vs Y?
This is another one of those loaded questions. Granted, it’s a valid question, but it is one which cannot be answered correctly without knowing the context. Not every tool fits every scenario. And it’s not all about comfort either. What you are comfortable with today is not necessarily what you were comfortable with, or proficient in, two years ago. Now, there are reasons why I may choose one technology over another. For example, if I am working with an established team, then we need to think of their strengths and the amount of time required to "ramp up" with a certain technology or pattern. Finances are also a concern in most cases. Everything from the cost of licensing software, to purchasing or maintaining hardware, to the cost of finding or keeping qualified developers is a variable. Software develop is not free nor is it instantaneous. Bottom line is that there is not one "correct" technology.

Have a question I didn’t cover here? Shoot me a note at:


Tell Them You’re Grateful

Every once in a while I end up sending a message to someone that probably makes them feel a bit uncomfortable. Someone noticed a message I sent to a friend this past week and said, "You really sent that? Isn’t that a bit gay?" (It was to a guy.) It wasn’t anything special… just a message letting them know how much I appreciate them and that I’m glad our paths crossed.

The way I look at it, life is simply too short, and people are often far too self-conscious, that they never end up admitting to anyone else when they really do feel good about them. And I don’t mean some cliché "copy n paste" chain mail. I’m talking about genuinely telling them how you feel. At most, people talk about the person in a eulogy after they’ve passed.

If you stop and think about it, there are several people in our lives who have made a positive impact. It may be your wife, a friend, a relative, a co-worker. Heck, it may even be some waitress in some late-night diner. Regardless, stop and pause for just 30 seconds to genuinely reflect on how they have positively impacted your life. Then, muster the courage and actually TELL them. If you need to, then even admit you feel awkward with what you’re about to say. The important part is that you actually tell them.

Don’t wait until it’s too late. If someone has positively impacted your life, take a moment to let them know. It may be the one thing that brings a smile to their day. Personally, if they have improved your life, I feel they deserve to know.


Easily Dockerize Node Apps

Quick script to Dockerize and tag your Node app with the current version number without having to dig through files for values. For me, this is important as I use Docker with EC2 and ECS on AWS. Using the project version number and name, from the project.json file, allows me to automagically tag the Docker image… which, in turn, allows me to easily deploy specific versions of the app or service for various release methods (blue/green, etc.).

First, the script itself …

#! /bin/bash

main() {

  local SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
  local BASE_DIR=$(dirname $(dirname $(dirname $SCRIPT_PATH)))

  local PKG_NAME=$(node -p "require('$BASE_DIR/package.json').name")
  local PKG_VER=$(node -p "require('$BASE_DIR/package.json').version")
  local CMD="cd $BASE_DIR && docker build -t $PKG_NAME:$PKG_VER  ."

  eval "$CMD"


The last three lines or so is the good stuff …

  local PKG_NAME=$(node -p "require('$BASE_DIR/package.json').name")
  local PKG_VER=$(node -p "require('$BASE_DIR/package.json').version")
  local CMD="cd $BASE_DIR && docker build -t $PKG_NAME:$PKG_VER  ."

The first two lines load the Node package and version into variables PKG_NAME and PKG_VER. That last line creates a proper command for Docker …

docker build -t my-cool-app:1.2.3

And, finally, I call this from my package.json file …

  "name": "my-cool-app",
  "version": "1.2.3",
  "description": "My Cool App",
  "main": "src/server.js",
  "scripts": {
    "build": "./scripts/dev/"
  "author": "Fred Lackey <>",
  "dependencies": {
    "cleaner-node": "^0.10.0",
    "express": "^4.17.1"

The end result is I am able to build my app into a Docker image by simply running …

npm run build

… with the result of having a Docker image built using the name and version of my app …

result example

… aaaand, a quick docker images shows it is available with the Node app and version as the Docker tag.

result images

I hope this helps.


Errors, Statuses, and Exceptions … Oh my!

Panic. AbEnd (or "abend"). GPF. Blue Screen o’ Death.

There are many names for it but I’m certain you’ve seen one of those situations where your computer throws a fit, gives up, and basically checks out on you. In the world of web programming this is essentially what a "500 error" is from an application’s standpoint. I’d like to take a moment to explain what it is and why you should never send it.

Simplified Version

For those of you who are in the "TL/DR camp", let me offer the cheat sheet version…

What are they?

Concept Level Definition
Status Request Context Overall status and reliability of the request and response.
Exception Method Scope Returned result does not match the shape of the method result.
Error Local Scope Problem or event usually preventing processing.

When to return them?

Concept Level Use When
Status Request Context Sent to the client on every response.
Exception Method Scope Handled by the calling method and translated. Never sent back.
Error Local Scope May be the cause of an exception. Only visible in the exception.

Which status code set to use?

Qualifier Status Code Range
Is your service working the way it is supposed to? 2xx
Did the client mess up what they were supposed to send? 4xx
Is your process or server dead and/or no longer reliable? 5xx


We all do it. For some reason, certain words are used interchangeably which are actually not interchangeable. So, to help clarify the mystery, let’s address those items up front.

Context vs Scope

In short, scope is the more granular of the two while context is more encompassing. Both have various modifiers like "global scope" vs "local scope" or "data context" vs "object context". So, while they both can be broken up at an even more granular level, we need some starting point which will allow us to work from without repeating the first month of a CompSci program.

Contexts (Request Contexts)

Whether you’re discussing the aging phrase "nTier" or the new fangled "microservices" buzzword, all multi-tier solutions do the same thing. They all receive requests from one app, service, tier, or layer and then make calls to other apps, services, tiers, or layers. Since I’m speaking primarily to web developers, our "context" will be referring to the request context of a typical multi-tier solution.

When a browser-based app calls a webservice, that browser based app is the "client" and our back-end service is the "server." The relationship of these two items, working together, for that moment in time is a context. However, the moment that back-end service calls out to a different webservice, then the webservice initiating that second call becomes the "client" and that upstream webservice is considered the "server". And, following the convention we discussed with the first client-server relationship, this second client-server pair is also a context. While both calls end up being chained together, they are both performing some type of logic in their own little world where that snippet of logic is only really valid for those few nanoseconds.

Let us take a peek at this scenario using some awe-inspiring shapes and colors…

example process

In this example, we show two separate contexts. The first context (in green) begins when the doIt() function is called from within the user interface. That function makes a call to the back-end webservice’s /api/do-it-now route and is not complete until it receives a response and returns it to the operation’s caller. In this example the server has determined it requires data and invokes a search() operation to call an upstream data service to fetch the needed information. Although one may depend on the other, that second context (in purple) is completely separate and detached from the first. Because they are separate, the status codes and error numbers are only considered valid and logical within each context.

Status Codes

Before we get into the dreaded 500 code, let us imagine a more easily understood code for a moment… the beloved 401 - Unauthorized status. Receiving this status from a webservice can only mean one thing: you did not have permission to call that service. Or, as the error name specifies, you were "unauthorized" to make your request. Assume, for a moment, that the second context (the one in purple) received a 401 - Unauthorized from the upstream webservice when fetching data. While this status code may make complete sense, should probably be logged, and is something we can troubleshoot, we would never send it directly back to the user interface as this would be a lie. Think about it. If we were to tell the user interface application that it was "unauthorized" we are saying that the UI application did not have permission to call the business service at all. And, since we happily received its request via the /api/do-it-now route, and began processing said request, that is clearly not true. What we do send back will need to make sense within first context and will be entirely dependent on whether or not the /api/do-it-now function can still proceed or how critical it is for continued processing of that initial request. If the data was absolutely essential, and we cannot continue processing at all, then we need to explain why that specific call failed. Since we obviously expected the business service to be configured with the correct credentials for calling the upstream data service some better status codes may be either a 417 - Expectation Failed or maybe even a 412 - Precondition Failed.


Rounding out this first comparison is the concept of scope. In the diagram above, the internal functionality, happening within functions like doIt() or search() are happening within that method’s scope (often referred to as "local scope" for each method). Similarly, if the doIt() method relied upon a BUS_SERVICE_URL variable that other methods share, more than likely, this variable would be set in the global scope. Regardless, just keep in mind that the scope is related to the smaller internal functionality within those services or libraries.

Errors vs Exceptions

The only real similarity errors and exceptions share is that the appear at the lower scope level. Aside from that, they are completely different and not interchangeable. The best way to think of them is that errors are bad and exceptions are not (at least, that’s how they’re intended). Exceptions are used to provide an intelligent response which does not match the documented shape of a method’s response and is used within the caller’s local scope. Errors, on the other hand, mean that bad things are happening and you need to take cover.


Let’s look at the following snippet…

const stepA = (value) => {
  if (result === 'redrum') {
    throw new Error('No wire hangers!');
const stepB = (value) => {
const stepC = (value) => {

export const doSomething = (value) => {
  let result = null;
  try {
    result = stepA(value);
    result = stepB(result);
  } catch (ex) {, ex.message);
  } finally {
    if (result !== null) {
      result = doSomething(result);
    } else {
      return false;
  return true;

In the example above, the public doSomething() function calls several smaller methods and returns a final boolean indicator to the caller. It does this even when an exception is thrown. The throw is used as a way to indicate processing could not continue in that one step. It does not convey the underlying system is unstable or malfunctioning. Exceptions are simply a means of returning a synchronous result to a caller which does not match the documented and expected result. So, if the caller is about to receive something other than the normal result, then go for it! Throw it, baby!

Playing Catch

Exceptions can be either handled or unhandled. This distinction exists for a reason. Many third-party components throw exceptions excessively while others should probably leverage this functionality more. The authors of those components are throwing exceptions to communicate with you and expect you to catch and handle the scenario. Regardless of whether from a third-party component or your own, it is the responsibility of the parent function to account for exceptions, handle them, and craft a meaningful response that makes sense within the calling operation’s context. The HTTP client Axios throws an exception any time it receives any status outside of the 200 range. The authors of Axios expect these errors to be understood and handled. It is assumed processing will either continue normally or a translated and intelligent message would be returned by the parent operation should processing need to stop. Every single exception should be handled. An unhandled exception, on the other hand, means something completely catastrophic has happened and we need to get all hands on deck. However, even if this were the case, in my mind, an unhandled exception would only ever be seen once since, once we know it can happen, we will add code to ensure we gracefully recover from it in the future.


Unlike exceptions, errors are generally bad and usually indicate a critical situation. For example, your database may be up and running but return an error when trying to execute a basic query. Or you may see the term **ERROR** in place of a result set. Either either scenario, you know that something bad happened under the hood.

Error Numbers

Since we’ve already discussed status codes specifically, I guess it’s only fair to spell out what an "error number" is and when they are generally used. In short, error numbers are commonly used by developers to document where an exact situation occurred in their source code (usually an undesirable event) and are usually never put in front of the end user (or, at least, not in a very prominent manner). Quality errors will be globally unique and only appear in one specific scenario. However, keep in mind that they are attached to errors. And, since errors are generally never displayed, neither will this be (again, unless it’s very discretely and [hopefully] with a plain-English explanation as to not cause panic to an end user).

Quick recap…

Before we go on, let’s ensure we are all on the same page …

  1. Errors may pop up during normal operation and may be the thing that causes an exception to be thrown. In most situations they are bad;

  2. Exceptions are natural and should be used in local scope to indicate when a method call will not receive its expected result shape. They exist for you to use;

  3. All exceptions are handled gracefully within the scope where they occurred and are translated to something meaningful to the rest of the application. They are generally not passed along; and,

  4. Status codes have nothing to do with errors or exceptions and, instead, convey the reliability of the response to the caller.

The 500 Family

First up: Mr. 500!

His official description says it all: "The server encountered an unexpected condition which prevented it from fulfilling the request." Bascically, it’s the web server’s way of saying, "Hey, you know all of of that time you spent accounting for all of the bad things that could possibly happen? Well, this is something totally new that you never thought would happen. You should probably plan for a long day of troubleshooting."

Consider the following event handler commonly used in a middleware pattern:

app.use(function (err, req, res, next) {
  res.status(err.statusCode || 500).send(err.message || 'Something broke!')

As the example shows, both a statusCode and message property are expected to be passed in. As the authors of our code we are the experts. Likewise, we have taken the time understand any third party or external components we may be leveraging. We therefore have an intrinsic opportunity to return an intelligent message in any scenario. This pattern assumes we have leveraged those opportunities but also continues processing should something happen which we never expected. In that unlikely scenario, a 500 status code is sent with the intention of communicating a completely unpredictable event.

The Rest of the 500 Klan

In general, the 500 series of status codes are meant to convey that something about our server is either not healthy or is broken. Some of these conditions may be temporary (like a 509 - Bandwidth Exceeded) and may resolve themselves at some point in time. Personally, I use the 501 - Not Implemented status regularly when adding a placeholder, that I don’t expect to be called (kinda like a "to do" note), or when removing logic from an older application. However, what is key here is that the status codes from 501 onward are also used intentionally when we need to intelligently communicate a condition about our server.

Opinions are like…

As with anything on this blog, please remember that these are my opinions. This is the way I like to work. And, yes, I realize I’m a bit anal at times (thanks, Mike, for pointing that out… again). After all, that is software development… a never-ending trail of opinions. Granted, our code actually does something in the end. However, along the way, we need to appease the opinion or feelings of an end-user or a business owner or, yes, even other team mates. It doesn’t mean any one of them is "wrong" or "right."

Productivity Programming

Ugly Date & File Date Organizer

Photos, screenshots, audio recordings … there are countless files that are stored (or should be stored) with the event’s date in the name. And, as it becomes easier to create these, they accumulate at an ever-increasing rate… usually in one folder without any type of organization. Of course, we could take the time to organize those folders, move files into proper folders, and delete what we don’t … oh, nevermind. Who am I kidding? Nobody does that.

For me, one simple step to greatly improve the value of these files is to organize them by their event date. This would at least help me find them if I need them. Grouping all files from the same day would help narrow down what may be relevant to that specific time frame. Sadly, there is no magical command, or even a utility, that will do this easily. And, even if one exists, it surely won’t work on all of the machines I use.

Well, now there is! Enter File Date Organizer and Ugly Date!

Of course, I chose to write these two utilities using NodeJS to ensure I can use them on macOS, Windows, and Linux. That’s a no-brainer.

Writing File Date Organizer came to a screeching halt the moment I pulled in the first few files and noticed that every utility I use to create screenshots formats the file names with a completely different convention…

Screen Shot 2016-07-29 at 6.11.png
Screenshot 2014-09-07 13.36.45.png

Even worse was the error I received when I tried to use MomentJS (the de facto utility for untangling these odd formats) to untangle those formats…

Deprecation warning: value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to for more info. After doing a bit of research, and seeing what options exist out there for detecting date formats, I understood why MomentJS decided to pull out their detection logic. Virtually every plugin or library out there uses basic RegEx (at best) to find four-digit years, two-digit minutes, or similar and fails miserably. They seem to all want so badly to return a value that they make assumptions along the way. In the end, most of them return bad values instead of no values at all… which, in my opinion, is the worst possible scenario. This is where Ugly Date comes into play.

Ugly Date is a bit of an experiment and takes a slightly different approach to parsing. Instead of simply using a series of RegEx patterns, Ugly Date contains groups of patterns and validators with the intent on locating possible matches, within the value, and then scores and compares those results with each other to return the best pattern versus returning any qualifying pattern. The change feels like a bit of a tradeoff. In the beginning, it will mean more maintenance and adding of patterns. However, over time, it should mean a better result when detecting more diverse patterns. Basically, you supply a string and Ugly Date parses it and returns both the date as well as a slew of potentially helpful information:

  "date": "2015-07-09T17:33:25.000Z",
  "hasDate": true,
  "hasDay": false,
  "hasTime": true,
  "pattern": "Screen Shot YYYY-MM-DD at a",
  "value": "Screen Shot 2015-07-09 at 1.33.25 PM",
  "values": {
    "YYYY": 2015,
    "MM": 7,
    "DD": 9,
    "h": 1,
    "mm": 33,
    "ss": 25,
    "aa": "PM"
  "locations": [
      "formal": "YYYY-MM-DD",
      "pattern": "YYYY-MM-DD",
      "position": 12,
      "type": "DATE",
      "value": "2015-07-09",
      "values": {
        "YYYY": 2015,
        "MM": 7,
        "DD": 9
      "formal": " a",
      "pattern": "h:mm:ss aa",
      "position": 26,
      "type": "TIME",
      "value": "1.33.25 PM",
      "values": {
        "h": 1,
        "mm": 33,
        "ss": 25,
        "aa": "PM"

Unlike its sister, File Date Organizer is far simpler than Ugly Date. There’s really nothing magical happening under the hood. You supply the source & target folders, tell it if you want to move or copy, overwrite or ignore, and let it go. In turn, it uses the logic within Ugly Date to parse each file and move them into a folder structure with a property date hierarchy:

The command itself is fairly logical with many “either / or” type of choices. Other than the source and target folder paths, the rest is somewhat a la carte. The basic command…

file-date-organizer \
  --source "/Users/flackey/Documents/Screenshots" \
  --target "/Volumes/MPHD01/Screenshots" \
  --use-name \

…can be swapped out with several other options. For example…

--move or --copy
--ignore or --overwrite
--use-created or --use-modified (for filenames not having a date)

It will also build your target folder structure using almost any of the date sections by using various --add switches. For example, adding --add-second causes the entire folder structure to be built all the way down to the seconds in the date value (ie, /YYYY/MM/dd/HH/mm/ss). There is a full list of switches on the project page. And, of course, the library can be used programmatically by pulling it into a Node project.

Granted, none of this is a perfect solution. And, Ugly Date is taking a very different approach to parsing dates compared to more traditional libraries. If nothing else, this satisfied the anal-retentive side of my brain.