DaedTech

Stories about Software

By

Lessons in Good Naming through Absurdity

There’s something I’ve found myself stressing a lot lately to people on my team. It’s a thing that probably seems to most like nitpicking, but I think is one of the most, if not the most, under-stressed aspects of programming. I’m talking about picking good names for things.

I’ve seen that people often give methods, variables and classes abbreviated names. This has roots in times where saving characters actually mattered. Methods in C had names like strcat (concatenate a string), and that seems to have carried forward to modern languages with modern resource situations. The reader of the method is left to try to piece together what the abbreviation means, like the recipient of a text message from someone who thinks that teenager text-speak is cute.

There are other naming issues that occur as well. Ambiguity is a common one, where methods have names like “OnClick” or even “DoStuff.” You’ll also have methods that are occasionally misleading — a method called “ReadRecords” that reads in some records and then actually updates them as well. Giving this a simple name like “ReadAndUpdateRecords” would take care of this, but people don’t do it. There are other examples as well.

All of this probably seems like nitpicking, as I said a moment ago, but I contend that it isn’t. Code is read way, way more often than it is written/modified, and it’s usually read by people who don’t really understand what was going through the coder’s mind at the time of writing. (This can even include the original coder, revisiting his own code weeks or months later.) Anything that furthers understanding becomes important for saving minutes or even hours spent trying to understand. Methods with names that accurately advertise what they do save the maintenance programmer from needing to examine the implementation to see how it works. When there is a standard like this through the entirety of the code base, the amount of time saved by not having to study implementations is huge.

Toward the end of achieving this goal, one idea I had was a “naming” audit. This activity would consist of the team assembling for an hour or so, perhaps over pizza one lunch or evening, and going through the code base looking at all of the names of methods, variables, and classes. Any names that weren’t accurate or sufficiently descriptive would be changed by the group to something that was clear to all. I think the ROI on this approach would be surprisingly high.

But if you can’t do that, maybe a more distributed approach would work — one that combines the best elements of shaming and good-natured ribbing, like having the person who breaks the build buy lunch. So maybe any time you encounter a poorly named method in the code, you rename it to something ridiculous to underscore the naming problem that preceded it. You bring this to the method author’s attention and demand a better name. Imagine seeing your methods renamed to things like:

  • ShockAndAwe()
  • Blammo(int x)
  • Beat(int deadHorse)
  • Onoes(string z)
  • UseTheForceLuke()

I’m not entirely sure if I’m serious about this or not, but it would make for an interesting experiment. Absurd names kind of underscores the “dude, what is this supposed to mean” point that I’m making, and it’s a strategy other than endless nagging, which isn’t really my style. I’m not sure if I’ll try this out, but please feel free to do so yourself and, if you do, let me know how it goes.

By

The Joy of Adding Code to Github

These days, a good portion of my time is spent on overhead tasks: management tasks, strategy meetings, this sort of thing. In my role, I also am responsible for the broad architectural decisions. But what I don’t get to do nearly as often between 9 and 5 these days is write code. All of the code that I write is prototype code. I’m sure that I’m not unique in experiencing drift away from the keyboard at times in my career — some of you do too as well. As you move into senior or lead type roles and spend time doing things like code reviews, mentoring, etc, it happens. And if you really love programming — making a thing — you’ll feel a loss come with this.

Of course, feeling this loss doesn’t have to be the result of having more overhead or leadership responsibilities. It can happen if you find yourself working on a project with lots of nasty legacy code, where changes are agonizingly slow and error prone. It can happen in a shop with such intense and byzantine waterfall processes that most of your time is spent writing weird documents and ‘planning’ for coding. It can happen in an environment dominated by loudmouths and Expert Beginners where you’re forced by peer pressure or explicit order to do stupid things. It can happen when you’ve simply lost belief in the project on which you’re working or the organization for which you’re working. And it almost certainly will happen to you at some point in your career.

Some call it “burnout,” some call it “boredom” and some call it “losing your way.” It has a lot of names. All of them mean that you’re losing connection with the thing you’ve liked: programming, or making a thing out of nothing. And you need that. It’s your livelihood and, perhaps more importantly, your happiness. But, you can get it back, though, and it isn’t that hard.

Lightbulb

Recently, I decided to order a few more home automation pieces (blog to follow at some point) and reboot the design of my home automation server to make use of a Raspberry Pi and a REST service in Python. I don’t know the first thing about Python, but after the parts arrived, and I spent a few hours reading, poking around, failing, and configuring, I was using Fiddler to turn all the lights off downstairs (code on github now — work in progress).

There is nothing quite like the feeling of creating that new repository. It’s daunting; I’m about to start learning a new programming language and my efforts in it will most certainly be daily-WTF-worthy until I learn enough to be passingly idiomatic in that language. It’s frustrating; it took me 15 minutes to figure out how to reference another code file. It’s tiring; between a day job taking 50+ hours per week and the work I do with my blog and Pluralsight, I’m usually coding at midnight on school nights. But forget all that because it’s exhilarating ; there’s nothing like that feeling of embarking on a journey to build a new thing. The code is clean because you haven’t had a chance to hose it up yet. There is no one else to tell you how, what, or when because it’s entirely your vision. The pressure is off because there are no users, customers, or deadlines yet. It’s just you, building something, limited only by your own imagination.

And what a powerful feeling. If you’ve got a case of the professional blues, go out and grab this feeling. Go dream up some new project to start and chase after it. Recapture the enjoyment and the excitement of the desire to invent and create that probably got you into this stuff in the first place.

By

Asking Questions That Change The World (Or At Least Your Group)

I recently asked a semi-rhetorical question on Twitter about health insurance in the USA. Specifically, it seems deeply weird to me that health insurance is tied in with employment. I mean, your employer doesn’t subsidize your homeowner’s, auto, or renter’s insurance, so why health insurance? Someone answered that this was an end-run around salary caps and restrictions that just kind of stuck around. This rang a bell, and I looked it up. Here’s an explanation that details how caps on wages during WWII were circumvented by offering this perk and making it tax deductible, and so a long, nonsensical tradition was born, established, and worked into our culture to a degree where everyone thinks, “that’s just the way things work.”

Many people respond to hearing questions of “why do we do this, anyway,” with something like, “hey, yeah, that’s a good question!” Once it’s pointed out to them, they recognize that perhaps an entrenched practice is worth questioning. Others balk at the notion and prefer doing things that are traditional, well, just because we’ve always done it that way. There seems to be something about human nature that finds ritual deeply comforting even when the original reasoning behind it has long expired. White dresses on wedding days, “God bless you” after sneezes, using signatures to indicate official permission, and many more are things that we simply do because it’s what we know, and if someone asked you “why,” you’d probably say, “huh, I don’t know.”

In this manner, software engineering resembles life. Within a group, things that originally had some purpose, reasonable or misguided, eventually become part of some unquestioned routine. I’ve seen shops where everyone was forced to use the same diff tool, where try-catch blocks were required in every single method, where every class had to implement IDisposable, and more, for reasons no one could remember. Obviously, this isn’t good. In life, tradition probably has an anthropologically stabilizing role about which I won’t speculate here, but in a software group, there’s really no upside.

Accordingly, I don’t want to team up with people that blindly follow cargo cult processes. It’s bad for the team. But who do I want on a team? It isn’t just people that are willing to forgo routines and rituals when they’re called into question and evaluated. I want people that think to do the questioning in the first place.

Don’t get me wrong. I’m not looking for iconoclasts that question everything whether or not there’s reason to question it or that rail against everything that others want to do. I’m looking for people that take no assumptions on faith and are constantly using data and objective metrics to reevaluate the validity of everything that they’re doing, even when those things are regarded as “no-brainers.” I want people that get creative when solving problems, expanding their thinking beyond obvious approaches and into the realm of saying “what if we could do it without doing this thing that we ‘have’ to do?”

It’s this kind of thinking that gave rise to NoSQL; what if a relational database weren’t required for every application? It’s this kind of thinking that turned the internet from a way to view documents into an application medium; what if there were applications that didn’t require CDs and installers? It’s this kind of thinking that changes the world, in software and in life. I want people on my team that wonder why their employer pays for their insurance, anyway.

By

Practical Math for Programmers: O Notation

It’s been a while since I’ve done one of these, and I didn’t want to let the series die, so here goes.

The “Why This Should Matter to You” Story

You’ve probably heard people you work with say thing like, “this is going to run in O of N squared, but mine is going to run in O of N, so we should use mine.” You understand that they’re talking about performance and, more specifically time, and that whatever N is, squaring it means more, and more is bad when it comes to time. From a realpolitik perspective, you’re aware that this O of N thing is something that lends programmers some cred if they know how to talk about it and from a career perspective, you understand that the Googles and Microsofts of the world seem interested in it.

But when your coworker talks about using his “O of N” solution, you don’t actually know what that means. And because of this, you tend to lose arguments. But beyond that, you’re also losing out on the ability to understand and reason about your code in a way that will let you see more pieces of the puzzle when weighing design tradeoffs. You could have a more intuitive understanding of how your code will perform in real world circumstances than you currently do.

Math Background

public void LinearTime(int n)
{
    for (int index = 0; index < n; index++)
        DoSomethingThatTakesOneSecond();
}

If you look at this method, do you know how long it takes to run? My guess is that you'd correctly and astutely say, "it depends on what you pass in for n." In this case, assuming that the method called inside the loop does what's advertised, the method will take n seconds: pass in 10 and it takes 10 seconds, but pass in 100 and it takes 100 seconds. The runtime varies in linearly with n. This said to run in O(N).

Let's look at another example.

public void QuadraticTime(int n)
{
    for (int index = 0; index < n; index++)
        for (int innerIndex = 0; innerIndex < n; innerIndex++)
            DoSomethingThatTakesOneSecond();
}

This one may be a little less intuitive, but you'll definitely notice it's going to be slower. How much? Well, it varies. If you pass in 2 for n, the outer loop will execute twice, and each time it does, the inner loop will execute twice, for a total of 2*2 = 4 executions. If you pass in 10, the outer loop will execute 10 times, with the inner loop executing ten times for each of those, so the total becomes 10*10 = 100 executions of the method. For each n, the value is n^2, so this is said to be O(n^2) runtime.

Let's take a look at yet another example.

public void ConstantTime(int n)
{
    DoSomethingThatTakesOneSecond();
    DoSomethingThatTakesOneSecond();
}

In this (poorly written because of the unused parameter) method, it doesn't matter what you pass in for n. The algorithm will always execute in two seconds. So, this means that it's O(2), right? Well, no, actually. As it turns out, a constant time algorithm is denoted in O notation by O(1). The reason for this is mainly convention, but it underscores an important point. A "constant time" algorithm may not be constant, per se, and it may not be one or any other specific number, but a "constant time" operation is one that is executed in an amount of time that is bounded by something independent of the problem at hand.

To understand what I mean here, consider the first two examples. Each of those runtimes depended on the input "n". The third example's runtime depends on something (the method called, for instance), but not n. Simplifying the runtime isn't unique to constant time. Consider the following:

public void QuadraticTime(int n)
{
    for (int index = 0; index < n; index++)
        for (int innerIndex = 0; innerIndex < index; innerIndex++)
            DoSomethingThatTakesOneSecond();
}

This code is identical to the second example, except that instead of innerIndex varying up to n, it varies only up to index. This is going to run in half the time that example two ran in, but we don't say that it's O(n^2/2). We simply say this is also O(n^2). Generally speaking, we're only interested in the factor of n and not any coefficients of n. So we don't talk about O(2n), O(n/12) or anything else, just n. Same goes for when n is squared or cubed, and the same thing goes for constant time -- there's no O(1/2) or O(26), just O(1).

One last thing to note about O notation (or Big O Notation, more formally) is that it constitutes a complexity upper bound. So, for example, if I stated that all of the examples were O(n^3), I'd technically be accurate, since all of them will run in O(n^3) or better. However, if you cite a higher order of complexity when discussing with others and then pedantically point out that you're technically right, they'll most likely not grasp what you're talking about (and, if they do, they'll probably want to stop talking to you quickly).

How It Helps You

In the same way that knowing about design patterns in software help you quickly understand a complex technique, O notation helps you understand and discuss how complex and resource intensive a solution is a function of its inputs. You can use this form of notation to talk about both algorithm runtime as well as memory consumed, and it gives you concrete methods of comparison, even in cases where you don't know the size of the input.

For instance, if you're doing some test runs on small set of data before pushing live to a web server and you have no way of simulating the high volume of users that it will have in the wild, this comes in very handy. Simple time trials of what you're doing aren't going to cut it because they're going to be on way too small a scale. You're going to have to reason about how your algorithm will behave, and O notation helps you do just that. On a small sample size, O(n^3) may be fine, but in production, it may grind your site to a halt. Better to know that going in.

O notation can also help you avoid writing terrible algorithms or solutions that perform wildly worse than others. For instance, consider the case of Fibonacci numbers. These are a sequence of numbers where Nth number is the last two numbers in the sequence added together: Fn = Fn-1 + Fn-2. The sequence itself is thus: 1, 1, 2, 3, 5, 8, 13, 21, etc.

Here is an elegant-seeming and crystal clear implementation of Fibonacci:

public int CalculateNthFibonacciNumber(int n)
{
    if (n == 0)
        return 0;
    if (n == 1)
        return 1;
    return CalculateNthFibonacciNumber(n - 1) + CalculateNthFibonacciNumber(n - 2);

}

It certainly demonstrates recursion and it's very understandable. But it also turns out to run in O(1.6^n), which is exponential runtime. We haven't covered that one yet, but exponential runtime is catastrophic in your algorithms. Ask this thing for the 1000th Fibonacci number and come back at the end of time when it's done completing your request. As it turns out, there is an iterative solution that runs in linear, O(n) time. You probably want that one.

This is the value of understanding O notation. Sure, without it you get that not all implementations are equally well performing and you may understand what makes some better than others. But understanding O notation gives you an easy way to remember and keep track of different approaches and how efficient they are and to communicate this information with others.

Further Reading

  1. Wikipedia
  2. A nice article for beginners
  3. Thorough explanation from stack overflow 'wiki'
  4. Academic but approachable explanation from MIT

By

My Initial Postsharp Setup — Logging at Assembly Granularity

PostSharp and Log4Net

I tweeted a bit about this, and now I’m going to post about my initial experience with it. This comes from the perspective of someone new at this particular setup but familiar with the concepts in general. So, what are PostSharp and log4net?

First up, log4net. This is extremely easy to understand, as it’s a logging framework for .NET. It was ported to .NET from Java and the product log4j a long time ago. It’s a tried and true way to instrument your applications for logging. I’m not going to go into a lot of detail on it (here’s a Pluralsight course by Jim Christopher), but you can install it for your project with Nuget and get started pretty quickly and easily.

PostSharp is a little more complex to explain (there’s also a Pluralsight course on this, by Donald Belcham). It’s a tool for a technique called “aspect-oriented programming” (AOP) which addresses what are known as cross cutting concerns. These are things that are intrinsically non-localized in an application. What I mean is, you might have a module that processes EDI feeds and another one that stores data to a local file, and these modules may be completely isolated from one another in your system. These concerns are localized in a nicely modular architecture. Something like, oh, I dunno, logging, is not. You do that everywhere. Logging is said to be an aspect of your system. Security is another stock example of an aspect.

PostSharp employs a technique called “IL Weaving” to address AOP in clean and remarkably decoupled way. If you’re a .NET programmer, whether you code in VB, C#, F#, etc., all of your code gets compiled down to what’s known as intermediate language (IL). Then, when the code is actually being executed, this IL is translated on the fly into machine/executable code. So there are two stages of compiling, in essence. In theory, you can write IL code directly. PostSharp takes advantage of this fact, and when you’re building your C# code into IL code, it interposes and injects a bit of its own stuff into the resultant IL. The upshot of all this is that you can have logging in every method in your code base without writing a single call to Logger.Log(something) in any method, anywhere. Let me be clear — you can get all of the benefits of comprehensive logging with none of the boilerplate, clutter, and intensely high coupling that typically comes with implementing an aspect.

Great, But How?

Due to a lack of time in general, I’ve sort of gotten away from detailed how-to posts, for the most part, with screenshots and steps. It’s really time consuming to make posts like that. What I’ll do instead is describe the process and, if anyone has questions, perhaps clarify with an addendum or links or something. Trying to get more agile everywhere and avoid gold-plating 🙂

And really, getting these things into your project is quite simple. In both cases, I just added a nuget package to a project. For log4net, this is trivial to do. For PostSharp, this actually triggers an install of PostSharp as a Visual Studio plugin. PostSharp offers a few different license types. When you install it in VS, it will prompt you to enter a license key or do a 45 day trial. You can sign up for an express version on their site, and you’ll get a license key that you can plug in. From there, it gets installed, and it’s actually really polished. It even gives you a window in Studio that keeps track of progress in some tutorials they offer for getting started.

With that in place, you’re ready to write your first aspect. These are generally implemented as attributes that you can use to decorate methods, types, and assemblies so that you can be as granular with the aspects as you like. If you implement an attribute that inherits from OnMethodBoundaryAspect, you get a hook in to having code executed on events in the application like “Method Enter,” “Method Leave,” and “Exception.” So you can write C# code that will get executed upon entry to every method.

Here’s a look at an example with some method details elided:

[Serializable]
[AttributeUsage(AttributeTargets.Assembly)]
public sealed class LogAttribute : OnMethodBoundaryAspect
{
    private static readonly ILog _logger;

    static LogAttribute()
    {
        SetupLogger();
        _logger = LogManager.GetLogger(typeof(LogAttribute));
    }

    public override void OnException(MethodExecutionArgs args)
    {
        if(_logger != null)
            _logger.Error("An exception occurred: ", args.Exception); 
    }
...

Leaving aside the logging implementation details, what I’ve done here is define an attribute. Any type or method decorated with this attribute will automatically log any exception that occurred without the code of that method being altered in the slightest. The “MethodExecutionArgs” parameter gives you information that lets you inspect various relevant details about the method in question: its name, its parameters, its return value, etc.

Getting Modular

Okay, so great. We can apply this at various levels. I decided that I wanted to apply it per assembly. I’m currently working at times in a legacy code base where a series of Winforms and Webforms applications make use of a common assembly called “Library.” This code had previously been duplicated, but I made it common and unified it as a step toward architecture improvement. This is where I put my aspect attribute for reference, and I decided to apply this at the assembly level. Initially, I want some assemblies logging exceptions, but not others. To achieve this, I put the following in the AssemblyInfo.cs in the assemblies for which I wanted logging.

[assembly: Log()]

This is awesome because even though PostSharp and the Aspect are heavily coupled to the assemblies on the whole (every assembly uses Library, and Library depends on Postsharp, so every assembly depends on PostSharp) it isn’t coupled in the actual code. In fact, I could just remove that line of code and the library dependency, and not touch a single other thing (except, of course, the references to library utilities).

But now another interesting problem arises, which is naming the log files generated. I want them to go in AppData, but I want them named after the respective deliverable in this code base.

And then, in the library project, I have this method inside of the LogAttribute class:

private static string GetLogFileFullPath()
{
    string friendlyName = AppDomain.CurrentDomain.FriendlyName;
    string executableName = friendlyName.Replace(".vshost", string.Empty);
    string appdataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
    string logPath = Path.Combine(appdataPath, "{CompanyNameHere}");
    return Path.Combine(logPath, String.Format("{0}.log", executableName));
}

I’ve made use of the Monostate Pattern to ensure that a single logger instance is configured and initialized and then used by the attribute instances. This is an implementation that I’ll probably refine over time, but it’s alright for a skunkworks. So, what happens is that when the application fires up, I figure out the name of the entry executable and use it to name the log file that’s created/appended in AppData under the company name folder.

This was great until I noticed weird files getting created in that folder. Turns out that NCrunch and other plugins are triggering the code to be invoked in this way, meaning that unit test runners, realtime and on-demand are generating logging. Duh. Oops. And… yikes!

My first thought was that I’d see if I was being run from a unit test and no-op out of logging if that were the case. I found this stack overflow post where Jon Skeet suggested an approach and mentioned that he “[held his] nose” while doing it because it was a pragmatic solution to his problem. Well, since I wasn’t in a pinch, I decided against that.

Maybe it would make sense, instead of figuring out whether I was in a unit test assembly and what other sorts of things I didn’t want to have the logging turned on for, to take a whitelist approach. That way, I have to turn logging on explicitly if I want it to happen. I liked that, but it seemed a little clunky. I thought about what I’d do to enable it on another one of the projects in the solution, and that would be to go into the assembly file and add the attribute for the assembly, and then go into the logger to add the assembly to the whitelist. But why do two steps when I could do one?

private static bool IsAspectLoggingEnabled()
{
    try
    {
        return Assembly.GetEntryAssembly() != null && Attribute.GetCustomAttributes(typeof(LogAttribute), false).Any();
    }
    catch
    { return false; }
}

I added this method that actually figures out whether the attribute has been declared for the assembly and, I only enable the logger if it has. I’ve tested this out and it works pretty well, though I’ve only been living with it for a couple of days, so it’s likely to continue evolving. But the spurious log files are gone, and MS Test runner no longer randomly bombs out because the “friendly name” sometimes has a colon in it. This is almost certainly not the most elegant approach to my situation, but it’s iteratively more elegant, and that’s really I’m ever going for.

Ideas/suggestions/shared experience is welcome. And here’s the code for the aspect in its entirety right now:

[Serializable]
[AttributeUsage(AttributeTargets.Assembly)]
public sealed class LogAttribute : OnMethodBoundaryAspect
{
    private static readonly ILog _logger;

    static LogAttribute()
    {
        if (IsAspectLoggingEnabled())
        {
            SetupLogger();
            _logger = LogManager.GetLogger(typeof(LogAttribute));
        }
    }

    public override void OnException(MethodExecutionArgs args)
    {
        if(_logger != null)
            _logger.Error("An exception occurred: ", args.Exception); 
    }


    private static bool IsAspectLoggingEnabled()
    {
        try
        {
            return Assembly.GetEntryAssembly() != null && Attribute.GetCustomAttributes(typeof(LogAttribute), false).Any();
        }
        catch
        { return false; }
    }

    private static void SetupLogger()
    {
        var appender = BuildAppender();

        var hierarchy = (Hierarchy)LogManager.GetRepository();
        hierarchy.Root.AddAppender(appender);

        hierarchy.Configured = true;
        BasicConfigurator.Configure(appender);
    }

    private static FileAppender BuildAppender()
    {
        var appender = new RollingFileAppender()
        {
            File = GetLogFileFullPath(),
            AppendToFile = true,
            Layout = new PatternLayout() { ConversionPattern = "%m%n" }
        };
        appender.ActivateOptions();
        return appender;
    }

    private static string GetLogFileFullPath()
    {
        string friendlyName = AppDomain.CurrentDomain.FriendlyName;
        string executableName = friendlyName.Replace(".vshost", string.Empty);
        string appdataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        string logPath = Path.Combine(appdataPath, "{CompanyNameHere}");
        return Path.Combine(logPath, String.Format("{0}.log", executableName));
    }
}