September 28, 2010

Nine non-development jobs professional developers would benefit from doing

Nine non-development jobs that professional software developers would benefit from doing once in their lives - not including the most obvious Software Engineer :P

  • Front line technical support - This will teach you that more often than not, business metrics [as flawed as they are from your developer point of view] drive the business, not your idealism towards your software. Your 'skewed' idealistic point of view has no weight in the call centre. This will give you an insight into just how much money large corporations waste on supporting each and every bug your software goes out with.
  • Second line technical support - Dealing with the simplest of problems that front line technical support can't figure out within the definition of their required metrics - i.e. their average call time, calls handled per shift etc.
  • Third line technical support - Dealing with calls from customers that neither front line or second line technical support can't figure out. Of the technical support jobs, this is the most fun. You only get the intriguing problems that nobody else can figure out.
  • Customer service in a call centre - Dealing with random calls regarding software, from "what does it do" to "I have no idea what I'm doing". You will have to find many ways of presenting the same information in different ways because not everyone 'gets it' the way you think they should. This will teach you patience... with a safety net, you can always put the customer on hold and freak out about how stupid they are.
  • Desk side support - Dealing with customers in person, sitting by the customer and fixing their problem for them or showing them how to fix it for themselves. The biggest lesson you will learn from this job is patience - without a safety net, you can't freak out because the customer is right there. Whether you consider the person an idiot or the smartest person you've met in your life, you have to keep an even temper and demonstrate compassion for their situation - even if underneath you're fuming.
  • Retail sales - The customer is important. This job will teach you many things: Personal interaction with unfamiliar people, body language, anticipation of customer needs and the value added upsell.
  • Integration specialist for someone else's software - Going to client sites and installing software into their production environments. This will teach you what happens in corporations once your software makes it into the wild. Just because it works on your test servers, with your test data doesn't mean it's going to work in the wild, on someone else's server, under someone else's control, with their data. It will also teach you the lengths you need to go to in order to integrate your software with other business applications.
  • Graphic Design - What's the point being able to make great software if it looks ugly?
  • Typesetting/Copy writing - What's the point in being able to make great software if nobody can read it?

If anyone's got any other non-development jobs that would be useful for rounding out a professional software developer, please comment! :)

September 24, 2010

Why company politics will cause your project to fail

How can one work in a company where nobody wants to be accountable for their comments, responses to questions or decisions? Recently I had an experience that I wish to serve as a warning to others that allow company politics to dictate how a project progresses.

There is a reason that you will hear software engineers the world over bitching about business analysts and design specifications. Because we know what happens when they don't happen adequately. I completely understand business analysts frustrations too, because that is one of my hats. The problem with specifications is that they need buy in from each of the stakeholders. But what should you do when the only people that have buy in are the ones approving your invoices? That can be an extremely frustrating process.

I wear many hats with this client: I'm a business analyst, requirements analyst, strategist, data architect, systems architect, software architect, team lead, coder and integration specialist. That wasn't by choice, nor was it what I signed up for, it just ended up working that way as it sometimes does. This setup does have some incredible advantages, but it can also bring incredible frustration that someone who wears only one of these hats will never see. Even though I wear all of these hats, I cannot design and build successful software for a client without the buy in of every one of the departments and staff I need information from. By buy in, I mean that this needs to be important to them. They need motivation to make sure that the information they're providing you is complete, accurate, well thought out and is in the best interests of the the parties they may be providing information on behalf of.

Having worked with one client for a while, I've grown familiar with their company politics and some members of their staff who are either unable to or unwilling to put pen to paper for fear that someone can categorically point their finger and say "you're to blame for this!" I can understand why, to be honest, I'd hate to think that someone was always looking to point the finger at me.

Usually I'm fairly flexible with my software design strategy, I can slack off in some areas and be more rigid in others. In some areas you can afford to be, in other areas you cannot. The design brief and interface specification are areas you cannot. Like most software developers, understanding a whole business process and reasons for it before I strategize on a design is non-negotiable. This time, like no other, I spent time with management discussing how things are done and how they want things to be done going forward. The biggest mistakes I made were ignoring politics and trusting that the information provided by management allowed me to draw the correct conclusion. What I'd failed to consider is that management who don't do the job day in day out "forget" things - important things that can and will completely derail the project at the design stage... and by "forget" I mean that it's in their political interest not to give you the information - whether it's a pissing contest with with another manager or being seen as relinquishment of power to an outside their kingdom.

I drew up mockups in photoshop to display the proposed interface design along with detailed process documentation. My request for feedback, was met with "that looks great, code it up". Being a small and fairly informal company, this has always been the way with the project since long before I came on board, and so I didn't want to rock the boat too much. They've always been against documentation in favour of results. I can deal with this in some areas on a small project, i.e. when bugs are reported to me, I may not write them up any further than brief notes to serve as a reminder of what the bug is. The design documents though, I don't skimp on. They include thought processes, things that need to be considered, thoughts on failure of certain strategies etc - something this company is keen to avoid at all costs. So this is something that I [with support of the manager I report to] have always been at odds with - It seems he'd given up arguing with the rest of the managers about it before I came on board. Anyway, I digress - it seems quite apparent that my designs and documentation weren't given more than a hurried glance to make it looked like they'd read it before the go ahead was given.

Let this be the warning: Just because you've drawn up the designs which were built on top of information provided by management and "signed off" by management, doesn't mean that what you have in your hand is completely or even partially correct. When management are giving direction for the design of software that they will not be using day in day out, consult those who will be using it. Do this as soon as you've written down and understood the information provided by management. If you don't, you risk (like I did) spending time writing a feature that cannot possibly be useful in the form you've developed it - even if it's exactly what management asked for and functions exactly the way they described it should.

My prediction is that this project is going to fail, miserably - how can I be sure? Because in my book, it already is. Not because of poor management of the project itself, nor because my predecessors or I haven't made every effort to follow best practices and adhere to and exceed industry standards. It's going to fail because internal politics make it impossible to implement any of the features in a manner that is useful to the users who require it to do their jobs effectively.

But who is to blame? The 'developer' of course [I use developer here loosely, it's really the business analyst that the client is pointing the finger at, though they don't know this - as far as they're concerned, the 'developer' is a catch all term for the vendor handling the project], not once has anyone put a pen to paper to say "I approve that this interpretation of the facts and processes are complete and accurate" and not once has anyone put pen to paper to say "I agree that this design is an effective solution to allow my staff to complete their jobs in the most efficent manner possible." So who is accountable? Well everyone avoided that responsibility because it's all about he said/she said. Even now, with the wheels falling off the project and even though I have gone over and above the call of duty to try and get these things rectified, there is still a refusal to change their practices.

Word of warning to the wise: You may not think that internal politics at a client have an effect on your design process, but if you don't want to be tied up in a project that's destined for failure from the outset, heed the warning signs. If politics amongst the management are dictated by the measurement of their dicks get out before it affects your work and makes you look bad.

Putting best practices aside for a moment there are undocumented and intangible things that are important for a project to succeed:

  • Stakeholder buy in. Everyone must be in the same boat working as a team towards one common goal. If any one/all of the stakeholders are not on board, don't believe in the project or are otherwise not happy with the project, they are a threat to the project.
  • Stakeholder priorities. Everyone must make the software development a top priority. It cannot be put aside as "I'm too busy to read this", "I'm too busy to write that", "I'm too busy to take part in this", "I didn't want any part of this". If they don't make it their first priority, they cannot complain when it doesn't take their views into account. If they don't make this a priority, they are a threat to the project.
  • Stakeholder accountability. If a stakeholder is not willing to be accountable for their decisions, accuracy of their input or completeness of their input then they are a threat to the project.

Lessons learned:

  • Never trust any information provided until you have proven that it's true. If that requires job shadowing, then so be it.
  • Political stakeholders are next to useless unless they're "at the coal face". Get process information those doing the appropriate job. Their manager or their manager's manager isn't good enough unless that manager also does that job. What makes the most sense to the users of the software, frequently isn't anything like what makes most sense to management.
  • It doesn't matter how much stakeholders attempt to avoid accountability, get a signature on a piece of paper that corroborates that your understanding is 100% complete and accurate before you start on strategy and designs. Do the same with your designs before you move to coding. If you don't, eventually the finger of blame will be pointed at you, no matter how unjust that finger pointing may be.

September 15, 2010

Reply: What is too simple and small to refactor

This code is partly inspired by Cory Fowler's refactoring of code provided by John MacIntyre in his last blog post - "What is too simple and small to refactor". John used the inheritance model to remove a boolean parameter he didn't like, Cory's was a slight departure and introduced funcs to inject the calculations, but still stuck with the inheritance model. I like Cory's approach, but I wanted to see if I could use funcs to entirely ditch the inheritance model - mostly just to see how far I could take the concept he introduced. My base calculations are all collated into a single static class with properties for each calculation returning a Func<float, float, float>. Each instance of employee has the calculation Func<> pushed in using dependency injection. This means that an employee could have an entirely custom calculation without requiring an instance of WageBase/CalculationBase or whatever other inheritance scheme was used in the other posts.
My WageCalculations class is basically a bunch of properties that return Func<float, float, float> this allows us to reference the calculations in a statically typed manner WageCalculations.BasicWithoutOvertime, WageCalculations.BasicWithOvertime etc.
My employee class is very simple, one of the constructors allows the PayCalculation property to be specified at instantiation. When we need to run the calculation, we just call empInst.CalculatePay(); So here's my employee class, nothing complicated:
Disclaimer: In the interest of keeping this blog post as short as possible none of the demonstration code contains any exception handling. Exception handling can however be found in the downloadable project at http://dl.dropbox.com/u/3029830/Prototypes/Prototype%20-%20WageCalculator.zip.
public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public float BaseRate { get; set; }

    public Func<float, float, float> PayCalculation { get; set; }

    public Employee(string firstName, 
                    string lastName, 
                    float baseRate, 
                    Func<float, float, float> payCalculation)
    {
        FirstName = firstName;
        LastName = lastName;
        BaseRate = baseRate;
        PayCalculation = payCalculation;
    }

    public float CalculatePay(float periodHours)
    {
        return PayCalculation(periodHours, BaseRate);
    }
}
Here's my PayCalculations class that provides all the basic pay calculations for the system:
public static class PayCalculations
{
    public static Func<float, float, float> BasicWithoutOvertime 
    { 
        get 
        {
            return (hours, baserate) =>
            {
                return hours * baserate;
            };
        }
    }
    public static Func<float, float, float> BasicWithOvertime
    {
        get
        {
            return (hours, baserate) =>
            {
                if (hours < 40) return hours * baserate;
                return ((hours - 40f) * 1.5f + 40f) * baserate;
            };
        }
    }
    public static Func<float, float, float> Salary
    {
        get 
        {
            return (hours, baserate) =>
            {
                return baserate;
            };
        }
    }
    public static Func<float, float, float> Contractor
    {
        get
        {
            return (hours, baserate) =>
            {
                /* Base rate */
                float subtotal = Math.Min(hours, 40) * baserate;
                hours -= Math.Min(hours, 40);
                /* Time plus a half */
                if (hours > 0) subtotal += 1.5f * Math.Min(hours, 20) * baserate;
                hours -= Math.Min(hours, 20);
                /* Double time */
                if (hours > 0) subtotal += 2.0f * Math.Min(hours, 20) * baserate;
                hours -= Math.Min(hours, 20);
                /* Doube time plus a half */
                if (hours > 0) subtotal += 2.5f * hours * baserate;

                return subtotal;
            };
        }
    }
}
Finally I've got my application code that sets up a bunch of new employees and passes their pay calculations into the constructor before calculating their pay for 50 hours:
class Program
{
    static void Main()
    {
        List Employees = new List()
        {
            new Employee("John", "MacIntyre", 40.25f, PayCalculations.BasicWithoutOvertime), 
            new Employee("Ben", "Alabaster", 40.25f, PayCalculations.BasicWithOvertime),
            new Employee("Cory", "Fowler", 2935f, PayCalculations.Salary),
            new Employee("John", "Doe", 150f, PayCalculations.Contractor), 
            new Employee("Jane", "Doe", 0f, (hours, baserate) => 3500),
            new Employee("Joe", "Bloggs", 34.25f, (hours, baserate) => {
                return hours < 15 ? 15 * baserate : hours * baserate;
            })
        };

        float hoursWorked = 50;
        Employees.ForEach(employee => {
            Console.WriteLine("{0}, {1}: ${2:#,###.00}", 
               employee.LastName, 
               employee.FirstName, 
               employee.CalculatePay(hoursWorked));
        });
    }
}
I'm not sure I can make it any simpler with this approach, I think I've taken the concept about as far as I can in this direction. Perhaps if anyone cares to take this a step further, they can write a contributory blog post and provide a link in the comments. I'd love to see other approaches to this refactor.

September 9, 2010

How many projects do I need in my solution?

Despite what people are saying, limiting yourself to three projects in a solution is as retarded as allowing things to get out of hand as far as 20... it's my belief that the fewer projects you can practically have in your solution, the better. But arbitrarily limiting yourself to any specific number is dumb. Use your common sense. Here are the questions I ask myself and the rules of thumb I follow for determining how many projects I need in my solution.

  • Am I writing an application that needs to be distributed across multiple servers?
  • Am I writing an application where different departments need different front-ends for the same data/business rules?
  • Am I writing a one off application that connects to its own database that will be used by one person or that everyone will see and use in the same way regardless of what it's being used for?

If you answered yes to the first 2 questions, then you probably need to separate your code into multiple projects or solutions. Ask yourself:

  • Does this code really need a separate project or solution than my application?
  • Is the code I want to put in the new project specific to this application or will it be useful in multiple applications? If it's not specific to this application, but it won't be useful in other applications, don't bother splitting it out.
  • Is the code I want to put in the new project dependent upon anything specific to this project? If the answer is yes, go on to the next question, if not, skip ahead to the last one.
  • Can any application specific dependencies be injected, thus removing the application dependency and therefore making it reusable in other projects? If the answer is no, then it shouldn't be its own project.
  • What is the realistic likelihood of the new project being reused? Truthfully. If it's unlikely to be reused, then it's a waste of time splitting it out.

Rules of thumb for defining the number of projects in my application solution:

  • Any code that is not specific to this application should be its own project(s), where practical in its own solution.
  • All projects should be as dependency free as is practical. This probably won't be none, it's usually far more effort than it's worth to make a project completely dependency free.
  • Any projects that are coupled so tightly that you cannot use either one without the other should be a single project. If there needs to be logical separation of concerns within that project, it should be in folders not projects.
  • Any project that can be used independently of other projects in the solution should be separated and linked with a binary reference at the earliest possible opportunity.

When I start developing a new application, I potentially start with the following projects in my solution:

  • Caching Layer [Potentially not needed] - This helps eliminate expensive hits on the database. It may not be needed depending on the application/circumstances/business needs. Most of my apps have this built into the data access layer, but a couple have required a centralized cache that can be hit with multiple instances of the DAL, thus required a separate deployment and thus a separate solution. Before the caching layer reached maturity enough that it could be used separately from my application though, it existed as a project within my solution.
  • Data Access Layer [Potentially already exists] - It would be ideal if this had no dependencies on any other project in your solution, but the fact is, it needs to return business objects, which are defined in your Business Object Layer, so your DAL and BOL are coupled, like it or not - although the BOL isn't dependent up on the Data Access Layer - it's a one way dependency.
  • Business Object Layer [Potentially already exists] - This doesn't need any dependencies on any other project in your solution. In an ideal world, your objects are just data storage devices for in-memory data. KISS. If your objects are dumb, it separates concerns and doesn't leave any awkward edges. I'm quite likely to use my business object layer in other projects because they're generic and don't do anything. I should be able to new up a business object and load it with data without needing to even reference my DAL. These are unchanging logical containers for data regarding company specific operations. In my current company that means: Stops, Manifests, Locations, Customers, Shipment. There's no logic, it's just data. These things don't change over time. A shipment is picked up from one location, delivered to another location and a customer gets billed for the shipment - that's trucking, it won't change until they invent teleportation. This allows my application to do what needs to be done. Like the Data Access Layer, this may have already been written and tested for other projects, if so, you'd just have a binary reference rather than a project/project reference in your solution.
  • Business Logic Layer [Optional] - Business rules that are non-project specific, i.e. if rules apply across all software in your organization - which they probably don't, so you probably don't need a project for this. These will relate to unchangeable business processes/practices. Given that very few business processes/practices are immutable, and given that if you change them, you'll likely need to modify your application, you probably don't need this layer separated from your application project. In cases where the rules apply to things that don't change very often - like the laws of physics, they could feasibly be stored in a business logic layer allowing multiple applications to make use of them. Usually though, business logic is application specific and as such, doesn't require its own assembly.
  • Application Layer (or Presentation Layer) - This contains application specific code: logic, helpers, utilities and configuration.
  • Projects for non-project specific utilities that don't belong in existing libraries - These are utilities being written for first time use and proofing with this project. These can't have any dependencies on any other projects in your solution (except amongst themselves) as once they reach maturity, you will be breaking them out into their own libraries and changing project references to binary references to remove clutter from this solution. If utilities belong in pre-existing libraries, they should be added to those libraries and tested before inclusion as a binary reference in this solution. Any chance to avoid adding a project to your current solution, will avoid headaches navigating around your code later. You should remove these projects and replace them with binary references at the earliest possible opportunity.

If you're really lucky and you've got a previously developed DAL and BOL and don't need any helpers that don't already exist in other libraries, you'll only need a single project in your solution. If you're not so lucky you'll be developing the DAL and BOL yourself. You'll probably also need at handful of non-project specific helpers that are logically unrelated to each other. These projects will sit in this solution until they've reached maturity enough that they can be broken out to their own solutions leaving a few binary references in their wake.

By the time you're finished, if you did it right you should just be left with your application layer and a bunch of binary references - a single project.

Of course, if you're writing a one off application and you're not going to have multiple applications floated over top of each of the different pieces, then there's precious little point in having any more than one project. You may as well just use folders in a single project from the outset.

There was an error in this gadget