Mentoring

The Importance of Mentoring

Photo by Okinawa Soba from his Flickr Account at http://www.flickr.com/photos/24443965@N08/2585609947/If you would allow me a personal moment for a second, I promise I’ll tie it in to something technical and relevant. Recently, my grandfather passed away at age 84. He was a brilliant man in both quantity of knowledge and the application of that knowledge – especially in the realm of finance. I won’t quote his accomplishments here in the interest of time and topic, but I assure you they were many.

As my father and I were handling all of the things that need taken care of following the death of a loved one, I got to thinking about my grandfather and what he knew. I got down a little bit thinking of how his lifetime of knowledge and wisdom has now been lost and humanity was poorer for it. However, upon further reflection, I realized that these things were not lost; they lived on with my father and me.

My grandfather raised my father, teaching him and guiding him along the way. My father in turn raised me with many of those same principles and my grandfather was there as well for help and guidance when called upon. Many of you know where I’m going with this. You knew two paragraphs ago, but I’m going to say it anyway! We need to mentor other developers in this same style.

We need to have Code Children and Code Grandchildren, Code Cousins and Code Siblings. Each developer goes on a journey; learning little by little along the way from books, blogs, user groups, trial and error, forums, etc. However, in my experience, I’ve seen very little “direct mentoring”.

“Direct mentoring” (according to me) is the deliberate pouring out of your knowledge into another person. You take ownership in their learning process; you become an essential piece of their growth. I’m talking about something different than “drive-by” question answering where we offer a little help and move on. True mentoring is a deliberate act. You have chosen a person (and they have accepted you) and you become someone taking an active part in their learning and development. You can suggest books to them, peer review code, answer questions, and be a person who holds them accountable on goals like learning a new language a year or reading a book a month.

I know that I am not covering brand new ground here. I also know that there are other people talking about this very thing. The “developer as a craftsman” group is very into this idea, describing it through parallels to apprenticeship in other vocations. I would like to see developers begin to mentor others and to in turn also seek out a mentor so that we can all learn from each other and give all of our hard earned knowledge some new legs by passing it on to someone else.

Errors

Fun With The iPhone – DFU Mode

I recently applied a firmware update to my iPhone and it broke. The phone wasn’t jailbroken and there was nothing shady about the dealing whatsoever. However, when I applied the 2.2.1 firmware, iTunes announced failure and my phone went into the revovery mode where it just shows the screen below.

iPhone Recovery Mode

I let iTunes attempt to recover my phone to no avail. I finally did some frantic Googling and came across a site called TheBigBoss.org, where I found a post about DFU Mode. I did what The Big Boss said and used the very strange shift+click* on the restore button in iTunes to allow me to choose what backup file went to my iPhone and finally was able to recover my phone.

* Note: Also from The Big Boss, “If you need to restore a specific version of firmware onto your device, rather than click restore, hold shift (PC) or option (MAC) and click restore. This will bring up a browse box where you can select the firmware you wish to program.”

I can’t believe that this had to be such a convoluted process, but I’m thankful to TheBigBoss.org website for all of the wealth of information it contained. Maybe if this blog can help one person deal with this problem just a little quicker than they would have otherwise, it is all worth it.

Errors

Rails Install Issue

So, I am making a serious go of learning Rails. I have installed it on my Vista machine before, but never really given it a go. So, now that I’ve got a Mac, I decided to try to learn Rails on it. I downloaded the Ruby One-Click Installer and installed it. Per its suggestion, I ran

sudo gem install rails

Then, I got this error

Bulk updating Gem source index for: 
http://gems.rubyforge.org ERROR:  
While executing gem ... (Gem::GemNotFoundException)     
Could not find rails (> 0) in any repository

I did some Googling and found out that I had to just run this code

sudo gem update

and select the correct packages to include. Then, I just reran

sudo gem install rails

and I was money in the bank.

I hope this helps anyone else who encounters the same issue. Now, on to working through some tutorials.

Code Tips

Liskov Substitution Principle

I was listening to Hanselminutes a few weeks back and Scott Hanselman had Uncle Bob Martin on to talk about the SOLID principles of object-oriented design. SOLID stands for

  • Single responsibility principle
  • Open closed principle
  • Liskov substitution principle
  • Interface segregation principle
  • Dependency inversion principle

Obviously, each one of those could warrant its own blog post and Robert Martin himself has written and spoken about them extensively. Uncle Bob did bring up a classic problem on Hanselminutes, though, that I wanted to take some time to talk about.

We who design object-oriented systems have a problem. We’ve been taught that the whole world is made of objects and that we are supposed to model our software after the real world. However, as I’ll cover in this post, sometimes that is a mistake.

The Liskov Substitution Principle says that “Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it” (Uncle Bob’s paraphrase). I have found this one somewhat confusing in the past, but I think that this Rectangle-Square problem explains the problem very well.

In math, the definition of a rectangle is “a parallelogram with four right angles”. One Webster’s definition of a square is “a rectangle with all four sides equal”. Right in the definition from the real world, a square is a rectangle. “Is a” is often a key phrase in object-oriented design used to denote an inheritance relationship.

So, let’s pretend we have the following code:

public class Rectangle
    {
        public virtual int Width { get; set; }
        public virtual int Height { get; set; }

        public virtual int ComputeArea()
        {
            return Width * Height;
        }
    }

    public class Square : Rectangle
    {
        private int _height;
        public override int Width 
        {
            get { return _height; }
            set
            {
                _height = value;
            }
        }

        public override int Height
        {
            get { return _height; }
            set
            {
                _height = value;
            }
        }
        
        public override int ComputeArea()
        {
            return base.ComputeArea();
        }
    }

Okay, that works. You can run code against it and at first blush it behaves like it should. However, the Liskov Substitution Principle says that you should be able to have

Rectangle r = new Square();

and have no problems.

While you can do that and can then operate on r as if it were a rectangle, there is a problem. A person who only knows about rectangles might do this to our r.

Rectangle r = someMethodThatWillReturnASquareSometimes();
r.Width = 10;
r.Height = 15;

They would then get entirely unpredictable results when they computed the area or even went back in to retrieve the properties (finding one had changed without their knowledge). A person who would want to operate in a safe way would have to eventually do the following:

Rectangle r = someMethodThatWillReturnASquareSometimes();

if (r is Square)
{
  // Special Square Processing
}
else
{
  // Normal Rectangle Stuff
}

That now pretty much defeats the purpose of using base classes and interfaces. If you have to know about derived classes and their implementation, you’ve lost the battle. I think that this is a great reminder to model objects logically how they affect the program, not how they reflect “real life”.

NMock

Intro to NMock

If you do Test Driven Development (TDD) for any amount of time and with any amount of serious effort you are going to run across a problem. Sometimes you can’t test one object without other objects being involved. Since you can’t properly test one object without isolating it, you need to fake or mock the others that you aren’t testing. The Wikipedia entry on Mock Objects discusses it in some more detail.

A good candidate for a mock are objects that return current information (and as such are hard to properly test) or objects that will make permanent changes to databases, for instance, and as such are also poor candidates for repeatable testing.

The first (and only) mocking framework that I’ve used is NMock. I chose it because my rule is “when in doubt, choose the product that is named ‘n’ and then what you are doing” (remember my NLog and NUnit posts?).

Examine the code below and my comments about what each section is doing.

using System;
using NMock2;

namespace PeteOnSoftware
{
    public interface IBlogEntry
    {
        string PostName { get; set; }
        DateTime PostingDate { get; set; }
        string PostBody { get; set; }
        bool SavePost();
    }

    public class NMock
    {
        public static void MakeMocks()
        {
            // Create the Mock Object "factory"
            var mockery = new Mockery();

            // Create our mock object based on the interface defined above
            IBlogEntry mockBlogEntry = (IBlogEntry) mockery.NewMock(typeof (IBlogEntry));

            // Here is the awesome part.  Here is where we define our Mock behavior.  Not only will 
            // our object now return true when the SavePost() method is called and "Intro to NMock" 
            // when the PostName property is called, but it will only do it one time - as we have
            // defined here.
            Expect.Once.On(mockBlogEntry).Method("SavePost").WithNoArguments().Will(Return.Value(true));
            Expect.Once.On(mockBlogEntry).GetProperty("PostName").Will(Return.Value("Intro to NMock"));

            // Output the results to the screen to see if it is behaving as we expect.
            Console.WriteLine(mockBlogEntry.SavePost());
            Console.WriteLine(mockBlogEntry.PostName);
        }
    }
}

This outputs the following to the output window:

True
Intro to NMock

However, check out the following code:

using System;
using NMock2;

namespace PeteOnSoftware
{
    public interface IBlogEntry
    {
        string PostName { get; set; }
        DateTime PostingDate { get; set; }
        string PostBody { get; set; }
        bool SavePost();
    }

    public class NMock
    {
        public static void MakeMocks()
        {
            var mockery = new Mockery();

            IBlogEntry mockBlogEntry = (IBlogEntry) mockery.NewMock(typeof (IBlogEntry));

            Expect.Once.On(mockBlogEntry).Method("SavePost").WithNoArguments().Will(Return.Value(true));

            // Output the results to the screen to see if it is behaving as we expect.
            Console.WriteLine(mockBlogEntry.SavePost());
            Console.WriteLine(mockBlogEntry.PostName);

            // We told the mock earlier that we would only call SavePost() once.  Let's see what 
            // happens if we call it again.
            Console.WriteLine(mockBlogEntry.SavePost());
        }
    }
}

This returns the following exception:

Unhandled Exception: NMock2.Internal.ExpectationException: 
     unexpected invocation  of blogEntry.SavePost()

One application of how that could be useful would be if you are testing your business tier to make sure that it does not call Save() on an object or into the DataTier more than one time per invocation. There are other options, as well. You can say Expect.AtLeastOnce or Expect.AtLeast(some int) or Expect.AtMost or Expect.Between or Expect.Never. The framework is so flexible. You can define how you want the mock object to behave depending on its inputs.

Examine the following code that makes the SavePost method return true if passed 1 and false if passed -1.

using System;
using NMock2;

namespace PeteOnSoftware
{
    public interface IBlogEntry
    {
        string PostName { get; set; }
        DateTime PostingDate { get; set; }
        string PostBody { get; set; }
        bool SavePost(int id);
    }

    public class NMock
    {
        public static void MakeMocks()
        {
            var mockery = new Mockery();

            IBlogEntry mockBlogEntry = (IBlogEntry) mockery.NewMock(typeof (IBlogEntry));

            Expect.AtLeastOnce.On(mockBlogEntry).Method("SavePost").With(1).Will(Return.Value(true));
            Expect.AtLeastOnce.On(mockBlogEntry).Method("SavePost").With(-1).Will(Return.Value(false));
            
            Console.WriteLine(mockBlogEntry.SavePost(1));
            Console.WriteLine(mockBlogEntry.SavePost(-1));
        }
    }
}

As you can see, NMock is flexible and can be very useful to a programmer who is doing unit tests. Next time, I’d like to take a look at Dependency Injection / Inversion of Control and how it can be used with Mocking to not only make your code flexible, but very testable.