Lines of Code Spent

I read an article a while back that talked about speaking of code changes as lines being spent, rather than written. As if code is something that we should conserve, like money... a limited resource of sorts. Unfortunately, it's not limited... and there's a lot of bad ways to spend it. However, this article struck a chord with me. I'm sure, as developers, we create a lot of our own problems. We write these solutions to be flexible and reuseable, but anytime there's a change in requirements, it seems we're back to the drawing board.

I've gone from being a junior developer, just trying to make things work, without breaking things, to being a little better and writing to design patterns and making everything extensible, doing minimal copy / pasting, making sure I understand every line of code that I wrote (which was a lot, during this period), to what I am today... simple is king. Code should be as complex as it needs to be... and no more.

Simple Code = Less Bugs

This is easy to say, and it makes a lot of sense, but it's much harder to pull off than it sounds. We've added a lot of abstraction to development, in general. As developers, we're using the highest end hardware... hardware to make gamers jealous. Our tools use a lot of resources, and our time is valuable, so it makes sense, but it also makes everything we build appear to be faster than it is for most other people. I've recently started using babel in my build tools to transpile ES6 JavaScript to JavaScript that most browsers in use, today, can understand. While this is great for me and my marketability... as well as, perhaps, future-proofing my code, it's not clear that the code I write in ES6 will transpile to simple JS. I'm sure there are some simple statements in ES6 that don't transpile so simply to ES5 compatible code (I've only just began, so I don't have any examples, yet).

How do we keep our code simple when we're not even writing the code that is being used on the page? Maybe it doesn't matter... maybe it only matters that it's simple for developers to read and understand. That's probably most important, but it does add a layer where bugs could happen, that is going to be hard for all but the most savvy JS developers to find and squash.

Be all that as it may, I've decided to start keeping track of how much code I check in... I'm going to try to do this weekly and talk about some of the more interesting things I've done during the week at the same time. So here goes... I'll start with week 3 of July

July, Week 3, 2015 Code Committed Report

CDK Global Code

So, last week, at my day job, I committed 11 changes. In those changes, I added a total of 499 lines... wow, that many??? That's what Fisheye says, anyway. I removed a total of 137 lines. So, my net is 362 lines spent at my day job. Which, if you consider I checked in a change on Saturday... I've got an average of 60 lines of code added per day.

Now, two of my changes canceled each other out, as one was backing out the other. Also, it looks like the majority of source added, is to test files, so that's not necessarily a bad thing, either.

One changelist, in particular, I have three changes to test files, and three changes to the corresponding source files, with the lines added to each of the source files being less than 10 in all cases, and the lines added to the tests being 25, 31, and 50. Testing is a good deal more wordy than the actual source in most cases, so I guess that's in line with expectations.

Greenlee County

For my consulting client, Greenlee County, I committed 5 changes in the last week. These all revolved around a new feature I'm trying to get working on their site to allow me to backup changes made directly to the files on the server (the IT manager's favorite way of making changes), as well as pulling my latest changes from the repository. In the end, this will make it so that I should rarely need to VPN into the network and remote desktop to the server (it's Windows).

These changes amounted to 141,224 lines of code added. Let me take a moment to note, these lines added were mostly added by my choice of project I started with for this. It turned out to be a fairly poor choice, as it gave me far more code than I needed or wanted. So, lines deleted are 109,539, for a net of 31,685 lines of code added... ouch. Hopefully, I'll winnow this project down some more in the coming weeks and see that total line count decrease pretty dramatically. I really do hate all the boiler plate Microsoft includes with all of it's projects.

South Elite All Stars

The pet project I'm working on for my daughter's cheer gym, South Elite All Stars, is a new responsive web site which will, hopefully, be going live the end of this week. The lines of code added for this project, which is still very young, is 795. The lines of code deleted is 2,872. So, the net is -2,077 lines of code. Not bad, but just a note that most of those lines of code are me trimming fat from the yeoman generated site. More details of this site design and development to come in the following weeks.

Change of the Week

The most interesting change in the bunch, is a rather large one (both the test and the source), and it's actually 2 changes, as I missed a necessary check on the first checkin. The purpose of this change was to include an image in a data model which was included in the source data model differently than the rest of the images. Take the following (simplified) example

"photos": {
  "photoCount": 67,
  "oem": {
    "OTHER": {
      "UNKNOWN": [{
        "path": "http://media-dmg-dit-ord.assets-cdk.com/evox/stills_0640/8915/8915_st0640_037.jpg",
        "title": "2014 Buick Enclave Vehicle Photo in Dallas, TX 75209"
      }, {
        "path": "http://media-dmg-dit-ord.assets-cdk.com/evox/stills_0640/8915/8915_st0640_039.jpg",
        "title": "2014 Buick Enclave Vehicle Photo in Dallas, TX 75209"
      }]
    }
  },
  "mainPhoto: {
    "path": "http://media-dmg-dit-ord.assets-cdk.com/evox/color_0640_032/8915/8915_cc0640_032_GWT.jpg",
    "title": "2014 Buick Enclave Vehicle Photo in Dallas, TX 75209"
  }
}
            

Now, if merging this singled out photo into the array above it were the only thing necessary, that wouldn't be very complex, at all... and would be very boring, besides. However, we're pulling images from two different sources. We obviously don't want duplicates, so we have to check our model for copies of this image before we add it to the beginning of our oem.OTHER.UNKNOWN array.

So, while the tests were fairly simple, they required a lot of extra code, as the current spec file needs some serious refactoring. It only required 3 extra test cases.

  1. It doesn't include the mainPhoto in oem.OTHER if it already exists in dealer photos.
  2. It doesn't include the mainPhoto in oem.OTHER if it already exists in oem.OTHER.
  3. It otherwise includes mainPhoto as the first photo in the oem.OTHER array.

Sadly, that was 134 net lines of code, to get those tests failing, appropriately. The source, on the other hand, was much more straight forward, only requiring 32 net lines of code to make the tests pass. The meat of this change is the function, hackInMainPhoto():

function hackInMainPhoto(photos) {
  var misc = "OTHER";
  var arr = "UNKNOWN";
  var main = "mainPhoto";
  var testOther = function testOther(source) {
    return source && source[misc] && source[misc][arr];
  };

  if (photos && photos[main]) {
    var dealer = photos.dealer;
    var oem = photos.oem;
    var pathFinder = function pathFinder(photo) {
      return photo.path === photos[main].path;
    };
    if ((testOther(dealer) && dealer[misc][arr].some(pathFinder)) ||
        (testOther(oem) && oem[misc][arr].some(pathFinder))) {
      return;
    }
    // make sure all of our necessary structure is present
    photos.oem = photos.oem || {};
    photos.oem[misc] = photos.oem[misc] || {};
    photos.oem[misc][arr] = photos.oem[misc][arr] || [];

    // plug in the photo
    photos.oem[misc][arr].unshift({
      path: photos[main].path
    });
  }
}
            

Only the last 3 lines of the function really do anything that the user will ever see... The rest is checking for existing structure and testing arrays to see if the photo is already included. I think that's what really makes it interesting. All of this setup and checking is necessary before we can actually do what the function was created to do.

Ultimately, a lot of this function will likely be refactored out to separate pieces, so it can be reused in other places in this model builder, but for now, that's the herculean effort required to unshift a single photo into an array in our model.

@phillipwills #CodeSpent