An exercise in TDD.

public class Program
    {
        static void Main(string[] args)
        {
            int sn = 123456782;
            int[] Digits;
            int AddedResult = 0;
            string s = sn.ToString();
            string sa = s.Substring(s.Length - 1, 1);

            int checkDigit = Convert.ToInt32(sn.ToString().Substring(s.Length - 1, 1)); //get the last digit.

            if (IsValidLength(sn))
            {

                sn = RemoveLastDigit(sn);
                Digits = ExtractEvenDigits(sn);
                Digits = DoubleDigits(Digits);
                AddedResult = AddedEvenDigits(Digits);
                AddedResult += AddOddDigits(sn);
                if (IsValidSN(AddedResult, checkDigit))
                {
                    Console.WriteLine("The number is valid");
                }
                else
                {
                    Console.WriteLine("The Number is not valid");
                }
            }
            else
            {
                Console.WriteLine("NotValidLength");
            }

            Char c = '2';
            Console.WriteLine("Character is {0}: ", Convert.ToInt32(c)); // returns 50
            string st = c.ToString();
            Console.WriteLine("string is {0}: ", Convert.ToInt32(st)); //returns 2;

            Console.Read();
            
        }

        public static bool IsValidSN(int AddedResult, int checkDigit)
        {
            return ((AddedResult % 10 == 0 && checkDigit == 0) || IsValidDifference(AddedResult, checkDigit));
            
        }

        public static bool IsValidDifference(int AddedResult, int checkDigit)
        {
            int nextHighestTens = AddedResult;
            while (nextHighestTens % 10 != 0)
            {
                nextHighestTens++;
            }
            return ((nextHighestTens - AddedResult) == checkDigit);
        }

        public static int AddOddDigits(int sn)
        {
            string s = sn.ToString();
            int i = 1;
            int addedResult = 0;
            foreach (char c in s)
            {
                if (i % 2 != 0)
                {
                    addedResult += Convert.ToInt32(c.ToString());
                }
                i++;
            }

            return addedResult;
        }

        public static int AddedEvenDigits(int[] Digits)
        {
            int addedEvenDigits = 0;
            string s = "";
            for (int i = 0; i < Digits.Length; i++) //extract each digit. For example 12 is extracted as 1 and 2
            {
                s += Digits[i].ToString();
            }
            for (int i = 0; i < s.Length; i++) //now add all extracted digits
            {
                addedEvenDigits += Convert.ToInt32(s[i].ToString());
            }
            return addedEvenDigits;
        }

        public static int[] DoubleDigits(int[] Digits)
        {
            int[] doubledDigits = new int[Digits.Count()];
            for (int i = 0; i < Digits.Length; i++)
            {
                doubledDigits[i] = Digits[i] * 2;
            }
            return doubledDigits;
        }

        public static int[] ExtractEvenDigits(int sn)
        {
            int[] EvenDigits = new int[4];
            string s = sn.ToString(); //12345678

            int j = 0;
            for (int i = 1; i < s.Length; i += 2)
            {
                EvenDigits[j] = Convert.ToInt32(s[i].ToString());
                j++;
            }
            
            return EvenDigits;
        }

        public static int RemoveLastDigit(int sn)
        {
            string s = sn.ToString();
            return Convert.ToInt32(s.Substring(0, s.Count() - 1));
        }
        public static bool IsValidLength(int sn)
        {
            return (sn > 9999999 && sn < 1000000000);
        }
    }

The Tests

    [TestFixture]
    public class SINTests
    {
        private int SinNumber = 123456782;

        [Test]
        public void TestValidNumber()
        {
            Assert.IsTrue(Program.IsValidLength(SinNumber));
        }
        
        [Test]
        public void TestRemoveLastDigit()
        {
            Assert.AreEqual(12345678, Program.RemoveLastDigit(SinNumber));
        }

        [Test]
        public void TestExtractEvenDigit()
        {
            int sn = 12345678;
            int[] array = new int[] { 2,4,6,8 };
            Assert.AreEqual(array, Program.ExtractEvenDigits(sn));
        }

        [Test]
        public void TestAddOddDigits()
        {
            int sn = 12345678;
            int result = 1 + 3 + 5 + 7;
            Assert.AreEqual(result, Program.AddOddDigits(sn));
        }
        [Test]
        public void TestDoubleEvenDigits()
        {
            int sn = 12345678;
            int[] original = new int[] { 2, 4, 6, 8 };
            int[] array = new int[] { 4, 8, 12, 16 };
            Assert.AreEqual(array, Program.DoubleDigits(original));
        }
        [Test]
        public void TestOddDigits()
        {
            int sn = 12345678;
            Assert.AreEqual(16, Program.AddOddDigits(sn));
        }

    }

Struggling to Ship: Prologue

About 21 days ago, I received The ShipIt Journal by Seth Godin, I had hoped this little journal would scare me into action. You see, I have a problem. I don’t ship.  Oh, I’ve released projects before; one a failure (over-time, and ended up being replaced a month later), and the jury is still out on the other; but I haven’t shipped any of my last three projects (Edit It, Stack Stats, A Blog Engine). They’re all in various stages of completion, from sketches on a piece of paper to actual prototypes written.  But they don’t exist yet. No one’s using them.  

In the eyes of myself and my peers, I’ve done nothing.  It’s a sobering thought that keeps me up at night.  In a profession where we’re measured by what we’ve released, the programmer that doesn’t ship is a charlatan.

The excuses are plenty and you’ve probably heard them all before.  Extra work, ballroom dancing, preparing for a wedding, you know, the usual. I have a precious few hours each night to spend, and it’s really easy for something to get in the way.

Or so my lizard brain keeps saying.

Perhaps deep down inside, I’m scared of my software sucking.  I want to make great software, but I know that once it’s out there, I’m vulnerable.  

The first step to conquering a fear is to face it.  This is me facing it.  Until these three projects finally ship, expect me to write about the process of trying to ship, the process of creating. If I fail, it will be public. If I succeed, it will be public. I have no idea what’s going to happen, only that I don’t have a lot of time to screw around. 

I want to make great software, but first I’ve actually got to make software.

The onslaught of bad variable names

I was poking around in a C# method the other day, trying to find out what the methods did at each level; it was an arduous task because of the complex nature of the process, made worse by the programmer who coded this method.

I blame the programmer because somewhere along the way, he coded something like the following (I’ve simplified it for your sanity and my own):


public static ArrayList TransformerHelper(params object[] inputArray)
{
    ArrayList result = new ArrayList();
    foreach (object item in inputArray)
    {
        if (obj is IContainer)
        { 
            result.Add((IContainer)item);
        }
    }
    return result;
}

There was really no way to tell why the programmer was doing this, and the variable names he chose didn’t help any. There are at least (5) problems with the preceding code:

1. TransformerHelper: What is it helping to transform? Why not say ConvertToContainerArray();?

2. the parameter name and type for inputArray is useless at best, and dangerous at worse.  Can any object in the world really come into the method?  In the method itself we’re checking for an object that implements the IContainer interface, so we should restructure our code to reflect that to all callers (most developers that write this code hide behind the, “But we’ve got to be flexible” mantra. If you ever hear that, grab a pitchfork. 

3. result is named poorly. Result of what? Of some unknown calculation?  What exactly is going on in there?

4. result is not type safe.  We know what types are going into that ArrayList, so we should use a generic collection to make our intent clear.  There’s also a performance improvement with using a generic list over an ArrayList.

5. There’s a double-cast in the body of the method.  The is operator checks to see if it’s of the type on the righthand side, and there is an explicit cast below it.  It’s a micro-optimization (unless there are a lot of objects in the Array coming in), but it’s useful to clean it up.

Bonus: Since this converts one type to another, we can make this an extension method and use it more idiomatically.

Here’s that same method after it has been cleaned up:


/// <summary>
///Used to Convert IBucketLists to Container.
///Not every type that implements IBucket also implements IContainer.
///This is used to convert the ones that do. The others we're not worried about.
/// </summary>
public static IList ToContainerList(this IList buckets)
{
    IList convertedList = new List();
    foreach (IBucket bucket in buckets)
    {
        IContainer container = bucket as IContainer; 
        if (container != null)
        { 
            convertedList.Add(container);
        }
    }
    return convertedList;
}

Much better. It hasn’t lost any of the meaning, and it will work as expected now. The next programmer that has to look at it should be able to tell what was going on without comments.

When you’re working with code, you’re not just solving the problem for you, you’re solving it for the next programmer that has to look at this code, and the next, and the next, and the next.  Code makes or breaks your business, and the harder it is to modify, the more likely your business will fail.  If you’re going by a method without cleaning it up, you’re gambling with your livelihood.

Skills Assessment Tests: A vital tool in finding talent

I never realized how much time I wasted phone screening candidates until I took a skills assessment test and realize it could have saved me and the candidate an hour of our lives.

A good skills assessment test:

 

  • Takes less than 15 minutes
  • Doesn’t contain easily google-able answers
  • Reflects Real Life Problems you’ve encountered 
  • Covers what someone should know to be successful on your team
Time? Who has Time?

Treat a candidate’s time as precious; 15 minutes should be an ample amount of time to take a test. Any longer and you risk the candidate losing interest, any shorter and you can’t really discern their skills.
Google Me Not
Asking questions straight out of What Every Good .NET Developer should know is a great way to have people type those questions into Google to get the answers.  The questions should be multiple choice (or if you have time to read the answers, short answer).  The questions to ask are questions that rely on derived knowledge, things that aren’t in the book but learned from experience.  
One such question is the following: 
Which of the following would an Interface *not* be used for?
A. To define a ‘has a’ relationship between two classes
B. To provide an implementation that that other classes can use
C. To avoid tight coupling
D. To allow for easier unit testing
Problems? As prevalent as off By One Errors
Just this week I had to diagnose Out of Memory Exceptions, a stored procedure that didn’t finish running, and Event handlers causing memory leaks.   And that’s just this week!
Your test should include problems that you’ve encountered, or problems that a developer might encounter during their time at your company.  I like to ask questions on .NET memory management, because it’s a topic that is easily overlooked, but really important for well-functioning application. I don’t expect most candidates to get it right, but I do expect for them to have a basic knowledge of how .NET handles memory management.
Make them Familiar with You

Your test should adequately be able to convey to the candidate what sort of topics your will come across. If you work on ASP.NET, then questions about the page lifecycle are good; if you work with design patterns, then those make great questions.  Bottom line is that anyone that reads your test should be able to understand what they’ll deal with on a daily basis.
Setting up the Online Assessment Test
Forget Brainbench. Their questions and answers are all across the internet.  Google has Google Docs, which let you create a Form you can use to create a multiple choice assessment test, and it provides a low-key way to create a test you can create once and use with any candidate — best of all, it’s targetted for your company.
Hiring is an involved process, and using a Skill test can save you time and money and weed out bad candidates.  What other reason do you need?

What do your Job Posting say about your company?

I like to surf the web for Job Postings.  Most of the time it’s because I want to see what other companies are up to; what the language du jour is, and whether or not I could see myself working there.  I believe every developer should be looking for their home, and a company’s job requirement is their welcome mat, so to speak. Take this posting from the 37signals Jobs board:

 

Hanscom Networks
Location: Palo Alto, CA
http://example.com

We have huge, naïve ambitions to change the world. Like most start-ups, we’ll probably be an abject failure.

We seek a designer to join us in our likely-futile goals. For the time that the company manages to avoid drowning in the the deadpool, we’ll work with you on creating a would-be beautiful website for our fundamentally ill-conceived product./p>

Various industry leaders, several of whom are not close family members, regularly use our product. They occasionally say encouraging things, likely to cajole us into fixing some crippling and unforgivably-overlooked bug.

We seek a mediocre designer who is regularly frustrated by their inability to make things that are as good as they should be to help us. We’d like somebody who writes <b> instead of <strong>, but not someone who writes, say, <B>. We’d like someone who isn’t all “durrrr” when they look at Photoshop, but we’d prefer someone who typically inflicts their general averageness on HTML instead of graphic design.

How can you not like that company? Hell, I’m not even a graphic designer and it makes me want to apply (I can barely run GIMP without googling my heart out).

They don’t have a monopoly on Job postings, however. Here’s a recent posting from The Motley Fool:

 

The Software Developer will be responsible for enhancing and supporting Motley Fool web applications and related systems.

Primary Responsibilities/Objectives
You will work on the full life-cycle software development of our web site, and some other non-web applications. You will help design high quality software solutions, skillfully leverage software patterns, implement code and unit tests with other developers, participate in peer review or pairing, test, and maintain the application, all using an agile and iterative scrum process framework in an open collaborative environment. You also may be involved in converting existing applications written in VB/VBScript/ASP to C#/ASPX, and required to play two-player Atari Gauntlet because Dwarf needs food badly.

    Core Competencies:

  • An understanding of Object Oriented analysis and design, and software patterns
  • Fluent in C# and ASPX
  • Microsoft .Net 2.0 experience
  • Experience with Microsoft T-SQL
  • Experience with unit testing and TDD
  • Strong communication skills
  • Web, e-mail, and Internet savvy
  • (X)HTML/XML/XSL/XSL-T/Ajax experience
  • Live public-facing web site experience is a plus
  • Agile and iterative methodologies experience a plus, particularly Scrum
  • Strong ping pong, bubble hockey, or foosball skills
    Preferred Qualities:

  • Meticulously detail oriented
  • Cautious
  • Consistent
  • Tenacious
  • Sense of craftsmanship
  • Motivated self-starter
    Foolish Qualities:

  • Uncompromising honesty
  • Approachable and willing to offer helpful solutions
  • Ability to search relentlessly for better solutions
  • Must be optimistic and have a strong sense of humor
  • Should handle constructive feedback well
  • Familiarity with The Motley Fool’s mission, our web sites, our products, and/or books, radio show, and newspaper column is a plus, as is investing experience

    The Motley Fool, Inc. provides equal opportunity to all employees on the basis of individual performance and qualification without regard to race, sex, marital status, religion, color, age, national origin, non-job-related handicap or disability, sexual orientation, or other protected factor.

    We should, however, make you aware that there is one notable exception to this policy. It is our strict and earnest intention — and the company’s historical record will bear this out — we will never hire any of the following: cyborgs, robots, replicants, or morlocks. Now keep in mind we are well aware that all of the aforementioned have intentions of world domination in the fu ture, but as of now we have no place for them at The Motley Fool … unless the year is 2122 and the revolution has already occurred. If that is the case we welcome our new cyborg, robot, replicant, or morlock rulers!!! Perhaps we have said too much?

That’s a job posting that says, “If you get what we’re talking about, then you should work for us.”

If you contrast that with the normal job postings that are out there, you can see who wins, really easily.

If you want developers that live and breathe programming, your corporate culture and job postings should reflect it. If not, just copy what you see on Monster.com, and you’ll get the caliber of candidate available on Monster.com.

My Programming Mantra

I’m not the smartest programmer out there. I’m certainly not the best.  I don’t work for Google, Microsoft, or Amazon.  I didn’t go to MIT, Yale, or Stanford, and I didn’t even major in Computer Science. I don’t know how to write a compiler, and I get fuzzy brained whenever I see a video game, knowing that there are programmers out there that can do that with their eyes closed.

I read The Pragmatic Programmer,Code Complete, and every book that gets recommended.  I read about 20 programming books a year. I read 20 different blogs, and I participate on Stack Overflow.  I am in awe of what some people know about C#. I know Perl, C#, and am learning C and Lisp.  I make mistakes daily, and some days I feel like I’m climbing Mount Everest.

I know my constraints, and I work each day to push past them.  With that in mind, I know that I’ll never be the guy that comes up with a new cryptographic algorithm, or finds a faster way to display graphics.  But even with those limitations in mind, I can make a difference in programming:

I can make software that people love to use.

That’s my mantra, and that’s what I judge my work against.