Tuesday, September 17, 2013

The Meaning of Life...

The Meaning Of Life As A Software Engineer When It Comes To What You Do At Work.  I know, it's not as sexy as just saying "The Meaning of Life", but if you're honest with yourself you'd admit that you wouldn't read a blog post with such a long title if I'd gone with the whole thing.

Anyway, this post is another slight deviation from software engineering, but I still feel it's important to software engineers and it technically is an "answer I couldn't find anywhere else" so I think I'm covered here.  I'm going to discuss (read: preach to you) what it means to be a software engineer.

As a software engineer your main, and possibly only, job is to make people's lives easier and/or better.  That's it.  That's the full meaning.  But it usually isn't so clear cut when you're actually working, especially when you're working for someone else.

At various points in my career I've come across some people-who-shall-remain-nameless-but-who-signed-the-check who wanted me and my team to focus on changes that make their lives easier while ignoring changes that would make a lot of other peoples' lives a lot easier and better.

It got me thinking, though.  When we're out there in the world coding away like happy little software simians we need to always be mindful of what we're doing and what kind of value we're providing.  It's really easy (for me at least) to start to slip down the this-could-be-more-elegant hole and the I-should-make-this-reusable-now-to-plan-for-the-future path while coding.  I like to ask myself one thing: who will this help?

Answering honestly, I can say that usually when I'm starting down one of the aforementioned roads I can easily pull myself back to what is important.  And what is important?  Haven't you been paying attention?  The only important thing in software engineering is making people's lives easier.  While you're coding, ask yourself these questions:

  • Whose job will be easier by using this feature?
  • Who will no longer get calls at 3 AM when something breaks because of this feature?
  • When this feature is released who will say "THANK YOU SO MUCH!!!!"?
There are other questions, but they're all on the same vein.  Just remember that what you're coding should have value to a user.  Always.

Sunday, September 15, 2013

Hide and Seek

This is a short post, and it's only kinda related to software engineering.  It's mostly just a fun thing to do when the Internet is angrifying you (yes, angrifying is a word because I said so).  If you use Google Chrome as your browser (you can also do this in IE and probably FF, too, but the steps would be different) you can right-click on an image on a page and choose Inspect Element (you can actually inspect any element on the page, not just images).  This will bring up the developer tools windowpane.  You can then change the style attribute of the image (or whatever element) and add "display:none;".  As soon as you press <Enter> the image (or whatever element) will disappear.  It will come back if you refresh the page, but for the moment it will be gone.  Check it out in pictures below.

Find the image you want to hide (the "Make extra cash" one in this example):






Right-click on it and choose Inspect Element (at the bottom of the menu)
You'll see the developer tools section at the bottom



The image you right-clicked should be highlighted so right-click on the markup for that image in the developer tools section and choose "Add Attribute"









Type in style="display:none;" and press the <Enter> key





Observe the results.





















Celebrate with a picture of a cute kitten:




Thursday, September 12, 2013

Bundles of Joy

Bundling (as it pertains to the MVC project type in Visual Studio) is a feature that was introduced... I don't know, you're not here for a history lesson.  If you're here at all you're probably here because something hinky went wrong with your bundling and you're searching the Internet desperately for something resembling an answer.  That, or you're bored.  Hopefully the first thing, though.

We had quite the charlie foxtrot the other day when it came to bundling and the issue wasn't discovered until we went to Production.  Oh, the good times.  First things first, bundling is the process by which you can tell the runtime to combine multiple resource files (such as css or javascript) together to be requested as a single document from the server.  There's a pretty good explanation here and it even has pictures!  Essentially, if you use many css files across all pages of your site (or javascript files, or you just want to reference jquery and jquery ui together) bundling can help speed up the performance of your site by turning those multiple calls into fewer calls.  In addition to bundling them, .NET will automatically minify your files (I know for sure that it will minify your javascript files and I'm pretty sure it will do the same for your css files), which means it will shrink them down to remove pretty much all white space.  It makes them nearly impossible for you to debug so you shouldn't just minify everything all the time, but it can help performance so you should definitely minify before production.

Now on to the problem.  We have an MVC3 application, which didn't include bundling "out of the box".  Instead I had to go through a bit of a long process of Googling and slapping together some suggestions until I found something that worked, which was ultimately to add System.Web.Optimization to my project (which also includes references to WebGrease and Antlr3.Runtime in case you see those in there).  After the reference was added, I just had to implement the bundling and everything worked like a charm.  Easy, right?  What, you want pictures or something?

Fine.

Here are the references in my project before doing anything...





















This is the menu you need to use.  The nuget package manager won't actually work for this.
















Using the above menu will open the Package Manager Console, in which you should type this.









Once you do that, your references should look similar to this.





















That's the setup part.  Now to actually create and consume the bundles.  Here are the using statements from my global.asax.cs file before I changed anything.


using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

I need to add a using statement for System.Web.Optimization so it looks like this.

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

Next, we add the code to build the bundles.

protected void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
        "~/Scripts/jquery-1.7.1.js",
        "~/Scripts/jquery-ui-1.8.20.js",
        "~/Scripts/jquery.unobtrusive-ajax.js",
        "~/Scripts/jquery.validate-vsdoc.js",
        "~/Scripts/jquery.validate.js",
        "~/Scripts/jquery.validate.unobtrusive.js"
        ));
 
    bundles.Add(new StyleBundle("~/bundles/css").Include(
        "~/Content/Site.css"
        ));
}

That's great, but we need to actually call that method we just created.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
 
    // Use LocalDB for Entity Framework by default
    Database.DefaultConnectionFactory = new SqlConnectionFactory("@Data Source=(local)");
 
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    RegisterBundles(BundleTable.Bundles);
}

Now that we have the bundles created we have to actually consume them.  This is in the head section of my _layout.cshtml file (note that you'll need to follow these same steps for all layouts used in your project).

<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

We make a couple of minor changes and we should be all set.

<title>@ViewBag.Title</title>
@Scripts.Render("~/bundles/jquery")
@Styles.Render("~/bundles/css")

Now, I may have told a very little lie earlier when I said "everything worked like a charm".  See, the reality is that everything appeared to have worked like a charm, but in reality was waiting like a lion at the watering hole, just waiting for me to get thirsty... or push to Production.  Apparently, Visual Studio disables the optimizations portion of bundling when the program is in debug mode.  This kinda makes sense, but it can really bite you if you don't know about it.  That's what happened to me.  I guess we deployed debug mode to our Dev, QA, and Stage environments (we used TFS build configurations to do it and I didn't have a hand in that).  When we went to Production for some reason (there's actually a long story behind "some reason", but I'm going to skip it for now) we deployed the release version of the code and we didn't use a TFS build configuration.  So when it hit Production, the optimizations kicked in and everything went to Hell in a handbasket.  Here's why:

.awesomeBackground {
    background: url(images/awesome.jpg)
}

Yup, the good ol' background image in the CSS file.  In my project I have the css files stored in /Content, which means that reference you see up there actually points to /Content/images/awesome.jpg.  But scroll back up and take a look at the code in my global.asax.cs file and you'll notice that the bundle I created is "~/bundles/css", which means when everything is minified and combined into a single file, the reference to the image will be /bundles/css/images/awesome.jpg.  You can probably guess how well that works when you don't actually have an image at /bundles/css/images/awesome.jpg; it looks awful.  But fear not!  There is a solution, and I'll even throw in a way for you to verify it's all working as expected in your Dev environment so you don't have to wait until Production to find out whether everything worked.

In order to get your image url references in your CSS files to keep their maps, you just need to name your bundle the same name as the original path.  So the updated RegisterBundles method looks like this.


protected void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
        "~/Scripts/jquery-1.7.1.js",
        "~/Scripts/jquery-ui-1.8.20.js",
        "~/Scripts/jquery.unobtrusive-ajax.js",
        "~/Scripts/jquery.validate-vsdoc.js",
        "~/Scripts/jquery.validate.js",
        "~/Scripts/jquery.validate.unobtrusive.js"
        ));
 
    bundles.Add(new StyleBundle("~/Content/css").Include(
        "~/Content/Site.css"
        ));
}

The difference is subtle, but really important.  I changed the name of the StyleBundle.  That allows the references to work as I expected them to.  As for how you can test this in your Dev environment (while still deploying the debug version of your code), do this.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
 
    // Use LocalDB for Entity Framework by default
    Database.DefaultConnectionFactory = new SqlConnection(@"Data Source=(local)");
 
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    RegisterBundles(BundleTable.Bundles);
 
    BundleTable.EnableOptimzations = true;
}

Yup, that one line tells .NET to go ahead and use the optimizations.  That should be all you need to do bundling in your MVC 3 application.  Fortunately, Microsoft decided to include System.Web.Optimization in a MVC 4 project type.  They also went ahead and bundled up all the jquery stuff for us so this is all a bit moot.  Hopefully it wasn't moot for you, though.

Tuesday, September 10, 2013

The Day 4.5 Broke Our Build

If your organization is like most (including mine) you don't rush out and get the latest and greatest tools the day they come out.  In fact, I can't think of anyone who does that.  We wait until there's either a) a budget surplus (yeah, because that happens in real life) or b) a need to upgrade.  That's how we found out that .NET 4.5 can break your build... even when you're programming .NET 4.0.  Allow me to explain.

We started our application rewrite (check out TDWTF for a funny explanation of the perfect scam) a couple years ago using MVC3 and .NET 4.0.  Of course we had to upgrade to Visual Studio 2010 to do this, so we did.  The rewrite got underway and a short way into it, Visual Studio 2012, .NET 4.5, MVC 4 and TFS 2012 all came out and we collectively decided we couldn't live without all of these things.  We all got VS 2012, we upgraded the TFS server to use TFS 2012, and we started on our merry way.  We decided to delay upgrading our target framework to 4.5 and also to delay upgrading our project to an MVC 4 project, but at least we were using 2012!

Then we used TFS to build and deploy our code to our dev server for the first time.  No sweat, right?  We right-clicked and hocus-pocused and voila! the site crashed... So what happened?  Well, this was the Day 4.5 Broke Our Build, remember?  So, obviously, 4.5 broke our build.  The end.

Or not.  In case you don't know, .NET 4.5 overlays .NET 4.0 so when you install 4.5 you "lose" 4.0.  That means that even if your code targets 4.0 the build server will build everything using 4.5, if 4.5 is installed on the build server.  So the build server builds your project using the 4.5 assemblies instead of the 4.0 assemblies and pushes your final code to the deployed server so it can actually be used.  Well, if the deployed server doesn't have 4.5 installed on it... BOOM!  This is where you start to get the MissingMethodException.  Ours was something along the lines of "Environment.CurrentManagedThreadId not found", but yours may be slightly different.  The point is, developing and building with 4.5 followed by deploying to a server without 4.5 will cause a problem.  The end.

Or not.  I wouldn't leave you without a solution (or two)!  Well, I might leave you without a solution, but this blog is about keeping track of fixes I've used so that I can reference them in the future and I wouldn't leave myself without a solution.  Our solution was to deploy 4.5 to our web servers.  That worked fine and honestly didn't blow anything up; honest!  According to Marc Gravell, you could also place the reference assemblies for 4.0 on the web server in the reference assemblies folder.  Since I haven't tried that solution I can't endorse it, other than to say that Marc's answers are always helpful and (as far as I can recall) correct as well so I trust him.

That's it!  That's the story of The Day 4.5 Broke Our Build.  The End.

No, seriously this time.  That was it.

Go home now.

There's nothing else to read here.

OK, fine here's another kitten picture.

Friday, September 6, 2013

Test-Driven Development

If you're like me, you've heard of Test-Driven Development (TDD) and you're kinda interested, but you haven't put a lot of time into figuring out how to do it.  Maybe you started down the path a long time ago and just got distracted (or bored, or you saw a squirrel).  Well, I recently had good cause to figure it all out and it turns out, it's really easy to learn.

The catch with learning TDD is that (if you're like me) you have to completely change the way you code against requirements.  No big deal, right?  So let me dive in and see if I can explain it simply for you (and remember that my blog is really more about creating an online repository of my own thoughts so I can figure out what I was thinking down the road).

TDD follows a pretty basic process that can be defined as: Red, Green, Refactor.  I prefer to refer to it as Fail, Pass, Clean Up, but that's just because I like to be contrary.  I find TDD easiest when I can identify acceptance criteria of my requirements.  Now, if you do agile you might be mentally protesting (or perhaps verbally, I don't know how unstable you are) that you're not supposed to have firm requirements in agile and that is sorta true, depending on your company's interpretation and implementation of agile.  But that's beside the point.  The point is that regardless of your development methodology you must have acceptance criteria.  Without acceptance criteria how will you know when you're finished coding and how will you know whether you've met your customers' needs?  So we identify acceptance criteria.  For simplicity, let's say our acceptance criteria is "the program displays the entered name".  Once you have your acceptance criteria, you can write your test.  Wait, what?!  Yeah, you create your test based on the acceptance criteria before you write any code at all.  That's why it's called Test-Driven Development.

[TestMethod]
public void ProgramShouldDisplayEnteredName()
{
    var p = new Program();
    var input = "Engineer_Andrew";
    var output = p.DisplayName(input);
    Assert.AreEqual("Engineer_Andrew", output);
}
That test fails, and that's a good thing.  The failed test is our "Red" part.  At this point, my program compiles, but the code doesn't actually do anything.  In fact, the code just throws an exception:

internal object DisplayName(string input)
{
    throw new NotImplementedException();
}

Now that we have a failing test (and we're proud of it) we write just enough code to make it turn "Green", or pass:

internal object DisplayName(string input)
{
    return input;
}

Since this test passes, we can move on to the third step; Refactor.  This is the part where we are going to refactor our code.  If you aren't familiar with that concept, it essentially means you're going to go back and make your code cleaner and/or more efficient and/or more extensible.  It can mean a lot of things, to be honest with you.  In this case it means we're going to do some validation of our input before we return it and we're going to return a string instead of an object:

internal object DisplayName(string input)
{
    if (string.IsNullOrEmpty(input))
    {
        return "Missing Name!";
    }
 
    return input;
}

The only thing left to do is re-run the same test as before and make sure it still passes.  It is also best practice to run all of the tests in your test suite to make sure you didn't inadvertently break something else.  As long as everything passes, you've met your acceptance criteria and you can move on to the next bit of code.

This is a seriously simplified example, but even on a larger scale the method provided here still holds.  Red, Green, Refactor (Fail, Pass, Clean Up).  That's all there is to it.

C# StringBuilder Quirks

As a software consultant, I see quite a bit of stuff that makes me wonder what the author was thinking when they wrote it.  Before you start yelling at me in the comments about how full time employees are great developers, too, I agree completely.  Often, what I'm looking at is from another consultant who didn't have an understanding of the domain he was in or he didn't really care about things like performance because after all he didn't work there anyway.  Then sometimes I'm looking at my own code.  Yeah, that happens.

Anyway, I'm at a client right now where we make use of the StringBuilder class to build different output messages.  We use this feature a lot so we'd like to have it working as efficiently as possible.  When this stuff was originally written, the team just instantiated a StringBuilder object and started invoking
   1:  .Append()
with various pieces of text they want to add. Like this:

   1:  var builder = new StringBuilder();
   2:  builder.Append("Hi");

Then a consultant came in and told them how terribly inefficient they were being with that implementation.  After all, when you just instantiate a StringBuilder object with the default constructor it only has enough room in memory to hold 16 characters.  16!  That's it!  Clearly that won't be enough.  So the consultant had the team create all of their string builders with enough capacity for 2048 characters.  Now, before I go on I should probably explain briefly exactly how the StringBuilder grows.

Basically, every time you try to append a string to the StringBuilder the capacity of the StringBuilder is evaluated.  If the string you're trying to append would cause the length of the string in the StringBuilder object to grow beyond the current capacity, new memory is allocated, the capacity of the StringBuilder is doubled, and your string is added.  So if you do what we did above, the default capacity is fine (16 characters is obviously enough to hold the three characters in "Hi!").  But then if you added something else like "Welcome to my blog.  I hope you enjoy what I have to say." you won't have enough room.  You're trying to squeeze 60 characters into an object that can only hold 16.  So your StringBuilder's capacity is doubled (to 32, for those of you who aren't friends with Math) and that isn't big enough, so the capacity is doubled again (to 64).  The end result is that you have caused memory to be reallocated twice and the capacity of the object has been quadrupled.

Ok, so that wasn't very brief, but it was important.  Back to the situation at hand.  You're probably thinking that I'm being pretty nitpicky about 2048 characters, and you would be right.  It is a big deal because we're using (relatively) obnoxious amounts of memory to build strings... just strings.  Assuming standard Unicode characters in the string (which is pretty fair in our use) each 2048 character StringBuilder takes up 4096 bytes in memory, even if we only put in 100 characters (which is also pretty fair in our use).  We use this implementation hundreds of times throughout our enterprise application, which accommodates hundreds of users at a time.  Do you see the problem here?

To be sure, there is a tradeoff to be had between pre-allocating the capacity of the StringBuilder to save the time required to reallocate that memory and wasting all of that extra capacity when you can be fairly certain it will never be used.  I'd rather allow the runtime to do what it is designed to do and reallocate the capacity as needed.

What's The Point?

Hello and welcome to my corner of the Internet!  If you're here, you may have come across something in your programming life for which you couldn't find an answer anywhere else.  Hopefully, I can provide an answer for you, but that's honestly not really my goal.  I mainly keep this blog to remind myself how I solved problems in the past so I can do it again in the future.  Along the way, I'll likely also post other stuff that I find helpful, but it will always have to do with software engineering.

If you're here for some other reason, bummer.  I'll try to console you with a cute picture of a kitten.