Personal Website of Levi Carter - Senior Software Developer with Marketpath from Noblesville, Indiana.
Read About Me
Close

Shortcuts Lead to Long Delays

Several years ago, I made the decision to write some function "shortcuts" which instantiated database instances inside my model layer. This made development faster and easier at the time but came with costs I did not fully appreciate at the time.

One of the costs was that the code library required twice the number of methods (one that allowed you to pass in a database and one that created it for you). While it's true that adding extra methods adds a negligible computational cost (computers are optimized to handle them with ease) there are other costs associated with increasing the size of your libraries: readability, maintainability, and testing to name just a few.

Another cost was that any change to the database initialization or abstraction may necessitate updating every library method that uses the database. Again, if you have a relatively small library this may not be much of a disadvantage but by the time you have implemented hundreds of methods and discover that you need to update them all you will quickly change your mind.

The biggest cost, however, was that it resulted in lazy development practices while writing the calling code. It is true that laziness is often a virtue in software development but only smart laziness. In this case the calling code simply allowed the library to instantiate the database nearly every time - which worked without any issues 99% of the time. Unfortunately it also caused some difficult and serious bugs the 1% of the time that it didn't work. For example:

  • Initializing a large number of database instances dramatically increased the likelihood that the server ran out of thread pool connections to the database.
  • Asynchronous code became much harder to handle
  • Calling multiple methods inside a transaction became harder to handle
  • On occasion, the same thread would attempt to create a second connection to a database before it was finished with the results from the first connection - resulting in odd situational errors that required significantly more work to debug and correct.

Thankfully, the solution to all of these problems was simple. Rewrite the library the way it should have been written the first time - by passing the database abstraction into each method and requiring the calling code to manage the database. This comes with a number of additional benefits, including:

  1. Smaller and simpler code base
  2. Consistency in calling code conventions
  3. Fewer bugs which are easier to troubleshoot
  4. Improved dependency injection
  5. Easier to test and analyze performance
  6. Slight improvement in overall application performance

Don't make my mistake. Be lazy but be lazy and smart. Do it right the first time.