To Thine Own Self Be True


    This post is both a rant and a bit of encouragement to any aspiring developers – this will not have code.

    Gabriel posted a rant earlier which sparked quite a few comments including a number from a fairly frustrated individual.  Ray posted a follow up to the rant and I feel compelled to comment as well.  I’ve had frustrations as both a job seeker and as a hiring manager so I have seen both sides of this particular coin.  I know the familiar themes, “Not enough quality in the marketplace”, “Employers won’t pay for quality”, “Employers won’t train inexperienced people”, “Employees use jobs as a training exercise to find a better paying job”, etc.

    I won’t offer rebuttals or thoughts on any of these because, frankly, I can’t.  I can’t tell you if they are true or false and if they are true I can’t change it.  I will offer some perspective.  

    I was a brand new manager in charge of a small (18) software development team when I came across Carla.  She was young and inexperienced.  She had an MIS degree and some minor work experience – not enough to make me believe she could work on my staff.  What Carla had in abundance was energy and intelligence.  As we spoke I began to believe in her and so I made her an offer.  I would pay her a very low salary for 6 months.  During that time she would have to maintain a normal workload and pass the MS developer certifications [I didn’t necessarily believe those indicated anything more than some knowledge of the language but . . .].  If she pulled it off I promised a regular position and a raise.  The last time I was in touch with Carla she was the manager of a development team at that company (my old job).  It wouldn’t surprise me to find out she was a Director by now (or even a VP).  

    To this day the single accomplishment I’m most proud of in my managerial career [such as it’s been] was giving her a chance.  In many ways it was a small thing, but it was one of the best professional choices I’ve made.  The reality is Carla did it all for herself.  I have no doubt she would be just a successful today if I had turned her away.  I could tell you stories about several other people from my time in that company – from the CTO who began in Customer Support (answering phones) to several folks on my teams who became very successful – and they would all sound the same.  These people succeeded because they invested in themselves and became valuable to the company and in the marketplace.  They did this largely on their own, without a company giving them money, time, or training.

    I could also tell you other stories.  About the man I had to fire after 6 weeks because he spent his time in the office looking for another job because he deserved better.  Or the man who felt I should give him a raise even though he hadn’t learned any new skills (even with the training I offered) or taken on any additional responsibilities.  These stories would also begin to sound the same and if you listened carefully you would hear the same complaint, “it isn’t fair”.  Maybe that was true – I’m not wise enough to know – but in the end, the difference between the stories of success and those of failure wasn’t about fairness – it was about focus.  That is what I looked for in employees back then and what I look for in peers today[I’m no longer a manager – just an average programmer].  I would rather hire a totally inexperienced person who has the energy and attitude to succeed than a twenty year veteran programmer who was convinced they deserved something.  I can’t teach someone how to work hard for something they desire.  I can’t teach attitude.  I can teach programming and if someone has the right attitude the rest will take care of itself.

    As for the other side – the one where I was on the outside looking in – that story is a bit like Carla’s.  I studied English Literature in college (U of O – Go Ducks!) and I left before I graduated so I don’t have a degree.  While in school I applied for a job at the University’s Network Services department as a student engineer.  I was in the wrong degree program and had no formal programming experience so naturally, I didn’t get the position.  As I was leaving – after being told “thanks but no thanks” – I came across a friend of my father’s.  He worked in the department and, upon hearing my story, convinced the director to hire me.  It was my chance and I took it in both hands.  I was the weakest link in a department full of geniuses but I learned as much as I could and drank from the fire-hose.  That job led to my first full time position (and my departure from the university without a degree) working for a school district that had just purchased a few UNIX servers, a bunch of Cisco routers, and a few hundred Apples with no-one to take care of them.  I made $30,000 my first year and spent 80+ hour a week learning everything I could while keeping the lights on for the district’s network of computers.  I became adept at shell scripting and C programming – and putting up with teachers but that’s another story.  

    I’ve had several jobs since that first one and several jobs that got away.  Many companies didn’t even give me a chance because I didn’t have a degree.  Several wouldn’t let me even interview.  Once I had some experience in programming (C, Perl, JAVA, VB), many companies would offer me lower salaries because I didn’t have a ‘typical’ programming background.  I’ve interviewed with one company in Austin twice and been rejected both times.  Was any of this fair?  Again, I don’t know.  Was it fair I got that job in school because someone knew my father?  Was it fair that companies rejected me without even giving me a chance to code with them – to see what I could do?

    But a better question – and one I’ll answer – is, “does it matter?”  No, it doesn’t.  I won’t tell you I was fine with the rejection.  I wasn’t.  It hurt and the next time I’m rejected it will hurt again.  But it never changed what I was going to do or how I was going to do it.  I’ve been programming professionally for over 16 years and I don’t believe I’ll ever stop.  I’ve been learning how to be a better programmer for over 16 years and I hope I’ll never stop.  Every year I find new challenges and ways to grow my skills – most of them outside of work.  I’ve volunteered at code-camps, attended book clubs, dojos, developer chats, lunch-and-learns all to be a better programmer tomorrow than I am today.  I don’t do this to get a better job and I don’t believe I deserve anything for all of my work.  I’ve done it for me and that is enough.  Coincidentally, I’ve managed to get hired a few times [I’ve never been out of work] and I’ve made a comfortable living doing something I love.  I don’t know if it’s fair or not.  I certainly don’t feel I deserve it, but I do feel grateful.  

    So, if you want to have a career in programming I suggest you spend less time worrying about the fairness of the market or getting what you deserve and more time learning your craft.  Even better, learn what you really want and go after it no matter what.  You will always face people, some of them good people, who will fail to see the best in you.  If you see it yourself and pursue it with all your will then things will work out o.k..

    And for anyone hiring out there I suggest you take a good look at the person behind the resume when making your choice.  Passion, drive, and determination will pay you tenfold if given an opportunity.  You will be hard-pressed to find a quality developer if you can’t find a quality person.

    OO Do I Know Thee?


    I was first introduced to the OO Programming Paradigm through JAVA in 1998.  Before that I did most of my work in C or shell scripts.  I liked it well enough but for business applications the paradigm felt wrong.  JAVA was a breath of fresh air and – at first – it seemed so natural.  I was indoctrinated into the well known 4 Concepts of OO and the whole Is A vs Has A relationships.  I dutifully created my Parent Objects which then had more specific Children (Dog Is A(n) Animal).  And it quickly began to feel as awkward as procedural programming.  In fact it was worse, because of a sense that my initial “this is so natural” reaction was correct and I must have taken a wrong turn.

    This last year has seen a major shift in how I perceive what OO is and how well (or not so well) the languages I’ve used represent or support OO.  The sequence happened a bit like this:

    First I went to Nothing But .Net and had many of my ideas about .Net stripped away.  It would be fair to say I left with more questions than answers but they were questions I’d been looking for since my JAVA days.

    Then I learned Objective C and with it new questions around what an object is, what it does, and how are they connected.  And do they always have to be connected?

    Then I started playing with Ruby and found even more questions about objects, behaviors, abstraction, and an OO application.

    All of which has lead me to this – I still don’t know The Truth about OO but I have a pretty good idea what it isn’t.  A better way to say this is: I have a better idea why my initial feeling was so strong and where I diverged from the “it just makes sense” view of OO.  Some of those errors (in no particular order):

    An Object is an encapsulates data and behaviors around that data.  Wrong.  Nope, not even going there.  Wrong.  Wrong.  Wrong.  This doesn’t mean an object can’t have data and behaviors.  Having and being are different things.  Don’t confuse them.

    Inheritance is a parent-child relationship.  Incomplete.  The parent-child metaphor has way too much meaning and side-effects that have no place in the idea of Inheritance.  Don’t confuse them.

    (C#) Interfaces are an abstract representation of a responsibility.  Too inflexible and limiting.  Narrows the scope of what they can be by (ironically) assigning them too broad a role in an application.

    Abstraction is primarily expressed through Interfaces and Abstract Classes.  Perhaps that is a vehicle supplied in a particular language but Abstraction is not organically connected to any mechanism to express it.  Thinking of it in linguistic programming terms limits it’s meaning and our ability to exercise it.

    I could go on to list many of the design patterns and principles you may have heard, including SOLID.  I’ve held most of these in an almost holy status at one point or another.  None of them hold The Key to OO nirvana and many of them – when viewed from an inappropriate perspective (which I often did) – can distract you from the potential and power of OO.

    Lastly, from the time of my euphoric introduction to JAVA until (painfully) recently I treated OO like a sacred hammer and saw most meaningful programming challenges as eager nails.  Sad-but-true.

    I now see OO as a useful paradigm to consider for human process driven applications (e.g. an application designed to mimic or assist in tasks a human would/could do).  With that broad definition I would understand people thinking I still have a magic hammer and see everything as a nail.  The reality for me is more subtle – so much so that I won’t elaborate in this post – and I’m beginning to see many problems I can solve with OO but I don’t feel I have solve with OO.

    I know I haven’t supplied many answers in this post.  You don’t need my answers.  You don’t really even need my questions.  You need your own questions and your own answers.  I hope mine can help you find yours.

    Are you Mocking Me?


    Jimmy has had a couple posts (mocks, mocks, and less mocks) that prompted Derick to post this on his experience with tests – I’d like to add my thoughts to mix.  First, let me say I’m not offering an answer to Derick’s question (sorry Derick), simply some ideas to consider.  If they help you, great.  If not, please join the mix.

    Not All Tests are created equal

    If I told you there are only X types of programs you can write to solve any problem and they could only be created a certain way, etc. you’d probably tell me to go do something rather unflattering and walk away.  Yet when someone talks rigidly about Unit Tests and Integration Tests as solemnly as one might discuss religious rites our incredulity is significantly diminished.  Is that a good thing?  What are automated tests after all?  Aren’t they applications we create to achieve a specific goal?  Is that goal always the same?  I hosted a discussion on testing a few months ago at work.  I began the session with a simple question, “Why do we test?”  The answers from that group were fairly broad – from the expected “to validate the expectations were met” to “to provide immediate feedback on an action we took”.  The next question was “What kind of tests can we do?”  And again the responses were varied.  I believe this is very healthy.

    My in my current position I find I have the following goals for tests:

    • When designing the roles in a new area of the application
      • Provide immediate feel for how my design choice shapes the behavior of the application
      • Provide immediate feedback that I am meeting the expectations
      • Keep my design focused on meeting the expectations for the Feature and no more
    • When creating a new feature using existing roles
      • Provide immediate feedback that I am meeting the expectations
      • Warn me if I’ve introduced a new role, altered an existing role, or broken existing features
    • When deploying my application to a CI or other environment
      • Provide assurance the environment is configured correctly
      • Provide immediate feedback about my interaction with external dependencies
      • Provide immediate feedback about how well my system meets the expected acceptable behavior

    There are a couple ideas I believe are valuable here:

    • Context – My goals and expectations vary by context; the context of what I’m doing and even the context of where I’m doing it (where I’m employed)
    • Roles – The behavior of a system is ultimately a collection of the data (nouns) and the roles (verbs) of a given feature.  If those roles are not being changed, I’m not designing anything new.  If they do, then I am in a design context
    • Scope – The scope of each context is important and should influence the scale of what I’m trying to do.  Being very specific in a broadly scoped context is an invitation for pain

    Because I have different contexts and goals I would be foolish to use the same tool for all of them, but isn’t that often the trap we get into with testing?  We say we follow a TDD, BDD, CYA, etc. style of testing and leave the conversation (and our minds) locked in a monolithic hell where nothing works quite right.  What if we left the grand ideas behind and just stated simply what we want.  When I’m designing something new I want tests to help me explore the roles I’m creating and how well they work together to create the expected behavior.  When I’m simply creating a new feature by composing the existing roles I just need to know I’m creating the appropriate behavior and staying within my expected architecture.  When I deploy, I want to see how the system behaves in it’s environment and how the features flow.  So, what does that look like?  Let’s take the code Jimmy posted in his original article and see.

    Design Mode

    public class OrderProcessor
    {
        private readonly ISmtpClient _client;
        private readonly IOrderSpec _spec;

        public OrderProcessor(ISmtpClient client, IOrderSpec spec)
        {
            _client = client;
            _spec = spec;
        }

        public void PlaceOrder(Order order)
        {
            if (_spec.IsMatch(order))
            {
                string body = “Huge frickin’ order alert!!!rnOrder #:” + order.OrderNumber;

                MailMessage message =
                    new MailMessage(“[email protected]”, “[email protected]”,
                                “Order processed”, body);

                _client.Send(message);
            }

            order.Status = OrderStatus.Submitted;
        }
    }
    When in design mode I want to start with a test that is focused on the expected behavior of the feature.  Jimmy didn’t supply that expectation so I’m going to make one up.  This feature is part of our commerce MVC application.  The expected behavior is that when a large order is placed, sales will be notified of the order and the order will be placed.  A controller action will take an order object and call our Order Processor object, save the order object, and decide which view to return based on order’s status.  For our purpose we’ll hold a notion of the system beginning at the controller.  Therefore, the behavior I want to create should be exposed solely by the OrderProcessor (let’s assume persistence is cross-cutting concern and not unique or valuable to this test).  Since it is the top level of our system I’d start by creating a feature test that instantiates the controller with a fake persistence object that allows me to control the order object that is passed into the action method and read the ‘saved’ order out.  I’ll let the IoC build the rest from the real objects.  If I was doing this with NUnit it might* look like this:

    using Autofac;
    using Moq;
    using NUnit.Framework;
    using Should;

    namespace FakeOrderSystem
    {
        [TestFixture]
        public class BehaviorProcessOrder
        {
            protected OrderController SUT;
            protected Mock MockSmtpClient;         protected IRepository FakeRepository;

            [TestFixtureSetUp]
            public void CreateSystem()
            {
                var builder = new ContainerBuilder();
                builder.RegisterType().As();             builder.RegisterType().As();             FakeRepository = new AFakeRepository();             MockSmtpClient = new Mock(MockBehavior.Loose);             builder.Register(s => MockSmtpClient.Object).As().SingleInstance();             var container = builder.Build();             SUT = new OrderController(FakeRepository, container.Resolve());         }

            [Test]
            public void Should_Notify_Sales_When_a_Large_Order_is_Placed()
            {
                //Arrange
                var largeOrder = new Order {OrderNumber = “O1234485”, Total = 300, Status = OrderStatus.New};

                //Act
                SUT.PlaceOrder(largeOrder);

                //Assert
                MockSmtpClient.Verify(c => c.Send(It.IsAny()));             FakeRepository.GetById(largeOrder.OrderNumber).Status.ShouldEqual(OrderStatus.Submitted);         }             } }

    *confession here – I didn’t spend the time to get this passing.  Do not consider this a ‘real’ example.

    I few things to point out here:

    1. The only test doubles here are for the SmtpClient (a mock because I only need to know it was called) and the Respository (a fake because I want more control)
    2. I could’ve used scanning to avoid specifying the interfaces (roles) involved and the objects acting in those roles.  I like being specific when I’m in design mode.  Once I’m done, I can always go back and replace this code with scanning/autowiring
    3. I want the system to remain the same for each test – the inputs and results are what define the context and expectations

    What does this give me?  For starters, it helps to clarify what I consider my system, what my expectations are of that system’s behavior in a given context, and what roles I believe should be enacted by the system to fulfill those expectations.  Once the design is complete (e.g. all expectations are met), I can re-use this test to confirm the system is unharmed by future additions to the application.  Indeed, if I remove the explicit registration, I could potentially replace the implementations below the controller and re-use this test.  It also helps me see the results of my design choices.  A few thoughts there – IOrderSpec is a bit too vague for my taste.  I’d want to explore that bit of the system more.  What is it’s role in processing an order and how can that role be more clearly expressed?  Second, I really don’t like where the ISmtpClient sits.  Even without seeing the implementation the order processor, I can spot a rub.  Did you see it too?  My expectation is that sales is notified, a behavior that is never expressed by an interface (role) in my system.  I believe I’m missing an abstraction – INotify.  Doesn’t change the need to use the mock for the mail client, but it does help to clarify how the expectation is met while providing more flexibility in the architecture for how that expectation is implemented (and maybe expanded in the future).  As I implemented each role, I would create unit tests for that single class using test doubles for all dependencies.  I would probably use an Automocking container (StructureMap has one, as does Autofac via the contrib project).  I would do this to allow me to be specific about the interaction (how the roles behave) as I design the system.  I might delete these tests after the design is finished, leave them alone as a warning for when my design has changed, or keep them in a separate test project I use when I’m re-designing my system.

    After re-factoring our system design test looks like this:

    using Autofac;
    using NUnit.Framework;
    using Should;

    namespace FakeOrderSystem
    {
        [TestFixture]
        public class BehaviorProcessOrder
        {
            protected OrderController SUT;
            protected AFakeMailClient FakeSmtpClient;  <——-  Now a Fake
            protected IRepository FakeRepository;

            [TestFixtureSetUp]
            public void CreateSystem()
            {
                var builder = new ContainerBuilder();
                builder.RegisterType().As();             builder.RegisterType().As();   <—- New Role that was ‘found’ by exploring the IOrderSpec role             builder.RegisterType().As(); <— The re-factored IOrderSpec             builder.RegisterType().As(); <—- Also ‘had’ a requirement for this state so put it in here to see how the design behaves
                builder.RegisterType().As(); <— we now have an abstraction that fulfills our missing ‘notify’ role             FakeRepository = new AFakeRepository();             FakeSmtpClient = new AFakeMailClient();             builder.Register(s => FakeSmtpClient).As().SingleInstance();             builder.Register(r => FakeRepository).As<IRepository>().SingleInstance();             var container = builder.Build();             SUT = new OrderController(container.Resolve());         }

            [Test]
            public void Should_Notify_Sales_When_a_Large_Order_is_Placed()
            {
                //Arrange
                var largeOrder = new Order {OrderNumber = “O1234485”, Total = 300, Status = OrderStatus.New};
               
                //Act
                SUT.PlaceOrder(largeOrder);

                //Assert
                FakeSmtpClient.VerifyMessageSentTo(“[email protected]”).ShouldBeTrue();
                FakeRepository.GetById(largeOrder.OrderNumber).Status.ShouldEqual(OrderStatus.Submitted);
            }

            [Test]
            public void Should_Notify_Manufacturing_When_a_Rush_Order_is_Placed()
            {
                //Arrange
                var rushOrder = new Order {OrderNumber = “O1234486”, Total = 30, Status = OrderStatus.NewRush};
               
                //Act
                SUT.PlaceOrder(rushOrder);

                //Assert
                FakeSmtpClient.VerifyMessageSentTo(“[email protected]”).ShouldBeTrue();
                FakeRepository.GetById(rushOrder.OrderNumber).Status.ShouldEqual(OrderStatus.Submitted);
            }
        }

    A consequence of this exercise is that I’ve decided (and expressed in the test) that my system has three top level responsibilities (roles): 1) to evaluate which actions should be taken based on the order’s state, 2) to set the status to submitted, and 3) to save the order (which will prompt other parts of the application to do things).  I refactored the OrderProcessor to perform these roles and added other dependencies (IEvaluateOrdersForActions) to help clarify the roles of the system.  I’ve also decided that the truly meaningful part of the email client is that the message was sent to the right person (I could also examine other aspects of the message).  This has removed my use of mocks completely as I need to retrieve the message from the client.  I’m now using two simple fake objects for more external dependencies.  How about the class that started this whole thing?  Our old friend OrderProcessor looks like this:

    public class OrderProcessor : IProcessAnOrder
    {
        private readonly IEvaluateOrdersForActions _evaluator;
        private readonly IRepository _repository;

        public OrderProcessor(IEvaluateOrdersForActions evaluator, IRepository repository)     {         _evaluator = evaluator;         _repository = repository;     }

        public void PlaceOrder(Order order)
        {
            _evaluator.Evaluate(order);
            order.Status = OrderStatus.Submitted;
            _repository.Update(order);
        }
    }

    Revisiting Jimmy’s statement on the value of test doubles I’d say this:  Mocks, stubs, fakes and the like are most valuable when they replace external dependencies.  Mocks, stubs, and the like are most valuable when they play a role in achieving the purpose for which you wrote the test.  I’m going to stop there for now.  I hope this gives folks some ideas to chew on.  A reminder, I’m not saying this is The Right Way or even A Right Way.  These are some ideas.  They need to worked and challenged if they are to have any value for you (or me for that matter).  I know I didn’t provide examples for deployment testing.  If I can find some time (and motivation) I’ll try to post some ideas on those as well.  Discuss.  (ala CoffeeTalk)

    Pablo’s Fiesta Preparation


    I just posted our invitation to the upcoming Fiesta.  If you’re planning to attend I hope you’ll take a few minutes to prepare yourself so we all get the most out of the experience. 

    If you have registered and you don’t plan on attending please let John know so we can make your ticket available to someone else – last time I checked we were almost sold-out.

    For myself, I’m ready for the following:

    • I know why software quality and craftsmanship matters to me.  I love programming so I want to do it well.  I know how I define quality today but that definition is constantly refined and it gets better when I hear how other people define it.  I have a family that needs me to make money and I want to continue doing that while doing something I love – creating software that works for users as well as possible.
    • I’m ready to take action.  I’ve spent the last several months working on my own personal improvement and it’s time for me to do more in my community.
    • I’m ready to hear (e.g. actually listen instead of mentally creating a rebuttal) opinions counter to my own.  I’m ready to have my opinions challenged and to explain them without taking offense.

    I hope you’re joining us.  I know many of the people who will be there and I believe this will be a great weekend for all of us.

    Los Techies Fiesta Invitation


    Pablo’s Fiesta Invitation

    How

    do you define, improve, and celebrate Software Quality and Craftsmanship

    in yourself, your organization, and your community? Los Techies is

    searching for answers to these questions and we’ve invited you to join

    us to explore together.

    We’re excited about this

    conference and the conversations we hope will take place . For those

    conversations to live up to our expectations and yours you must come

    prepared to:

    Engage in open conversations. If you

    have an idea, know the reasons for that idea and be prepared to discuss

    them without taking offense. If you disagree with an idea, be prepared

    to criticize the idea, not the person.

    Know why Software Quality and Craftsmanship matters to you.

    We know why it matters to us – we’re inviting you to hear why it

    matters to you. If you don’t know why, take some time to explore the

    answers before you attend.
    **
    Provide actionable ideas and take action after the conference is over.**
    If all we do is discuss a few ideas, solidify viewpoints, and bolster our egos this conference won’t

    have done much. We want to leave the Fiesta energized to make our profession better fit our dreams.

    If you you walk out of the Fiesta muttering to yourself we never talked about the really important issues you cared

    about, please notice the person responsible for that is you.

    It’s

    time to get to work. What are the issues and opportunities for Software

    Quality and Craftsmanship you care about? What are your ideas,

    questions, and desires for resolution and future directions in Software

    Quality and Craftsmanship? How do we make those ideas happen now – all

    the way to the level of implementation?

    Sponors

    Event: Los Techies Fiesta

    Date: Friday, February 26, 2010 at 6:00 PM – Sunday, February 28, 2010 at 12:00 PM (CT)

    Location:
    St Edwards Professional Education Center
    9420 Research Blvd
    Echelon III
    Austin, TX 78759

    For more information click here: Los Techies Fiesta

    Pragmatic Thinking and Learning – A Review


    Pragmatic Thinking and LearningSo, back in August (or was it September?) the members of Los Techies were offered a sweet deal from The Pragmatic Programmers – pick any book (free), read it, and write a review.  There were no strings attached so we could give our honest opinion.  I picked Pragmatic Thinking and Learning (Andy Hunt) and eagerly awaited my package.  For this to be a thorough review I should admit that I have already read and own several of The Pragmatic Programmers books.  I’ve long considered The Pragmatic Programmer to be one of the few “must read” books for any programmer.  So, it is fair to say I’m pre-disposed to the style and opinions of The Pragmatic Programmers team.

    To start, my ‘package’ first arrived as an email, letting me know my book was ready for download (DRM free) in three diffferent formats (PDF, EPUB, MOBI).  Tickled by this unexpected event, I downloaded my three formats and loaded it up on my iPhone.  Do yourself a favor – don’t try to read a-n-y-t-h-i-n-g of substance on the iphone.  This false start was short lived because I soon received a dead-tree (paper) copy in my mailbox.  Yea for murdered trees!  Two weeks later I had finished the book (about the end of September).  Now I faced a dilema – and my first warning about this book – even though I had read every word of the book (many several times) I couldn’t really write a serious review.  This is because this book cannot be simply read – it must be exercised, practiced, and tested to give you the full experience.  There are many exercises throughout the book, some that require you to spend 20 minutes or more several times over several days to truly be prepared to evaluate the premise.

    Undaunted, I began to re-read the book at a more sedate pace, performing each exercise until I was satisfied I could judge it fairly.  This put me squarely up against my life-long nemisis – procrastination.  There were a few weeks (here and there) when I simply didn’t give the book enough time and my progress stalled.  If you have a difficult time staying on-task over several weeks you’re going to get less than you could out of this book.  I’ve finally finished the book – again.  I can say without any hesitation it has joined my short-list of ‘must read’ programmer books.  If you are a programmer and you haven’t read this book stop.  Now.  Yes, now.  Go get the book here and start reading.  What are you doing?  Why are you still reading this?  I said now!  What?  You want to know why?  Where is the trust in this world anymore?

    O.k. why do I like this book so much?  I suppose I could’ve told you that before I told you to buy it but . . . now you’ll know why you bought it.  You did buy it – didn’t you?   I can see we’re going to have a problem.  O.k., fine – what did I like about the book:

    1. Much like The Pragmatic Programmer, this book doesn’t give you “The Answer” or profess that everything in it works the same for everyone.  Andy makes a point to stress “Consider the Context” and this is a big part of the power of this book.  Of course, if (when) you read this book you’ll discover I probably like this aspect at least in part due to my generational bias.  Wanna know what that means?  To bad, you’ll have to find out for yourself.
    2. I firmly believe your brain is the most important tool you will ever have.  I’ve spent my entire life trying to improve that particular piece of equipment and I intend to continue the process until my brainwaves cease.  Andy has spent a huge amount of time reading different books on how the brain works and condenses his learning into a compact format for us.  So, there’s a lot of bang for your reading buck.
    3. This book has huge re-readability.  It has been become a reference for me that I return to often – not necessarily just for the material Andy has supplied directly, but also as a reference for other books I’d like to go read.
    4. I finished this book inspired, empowered, and encouraged that I could do more in less time than I imagined – in short, my learning pace has accelerated noticeably.

    What wasn’t so cool?  Well, I’ve ended up with a much longer list of books I’d like to read.  While Andy does an admirable job of bringing a great deal of material to bear in a concise format he does so at the expense of being somewhat terse.  If you, like me, have a curiosity that is not satisfied by a synopsis of a larger body of work then the bibliography of this book will supply you – as it has me – with a surplus of reading material and a paucity of spare time.

    O.k.  Ready to go buy it now?  I mean, I’d loan you my copy but I’m using it.  Enjoy.  I certainly have.

    If You’re Looking for Nothin But .Net . . .


    I attended JP’s Nothin But .Net course (http://www.jpboodhoo.com/training.oo) last week and I wanted to share my perspective with anyone who might be considering the course.  I really enjoyed the experience and I’d happily recommend the course . . . to the right people.  Rather than do the usual “I recommend this course because blah, blah, blah” I’d like to tell you why you shouldn’t or wouldn’t want to attend.  If you make to the end of this post and still want to attend, I highly recommend you do as soon as possible.

    If you already have an incredibly strong understanding of the .Net Framework, TDD, BDD, DDD, or if you have a style/way of programming that is perfectly effective and satisfying for you then don’t attend.  If fact, if you’re any good at teaching, you might wish to start your own course.

    If you are very comfortable with your life and your method of programming and you don’t wish to be challenged then this would be a bad course for you.  JP will challenge you to improve your coding skills and your life.  Not your idea of a good time?  Stay home.

    If you are very weak in .Net, especially if you are new to it, wait.  Learn more about the framework, delegates, generics, and unit testing before you consider this course.

    If the idea of spending 80+ hours in five days focused on .Net development skills fills you with dread, don’t go.  Monday night – 10:30pm, Tuesday – 11:30pm, Wednesday – 12:30pm, Thursday night (well really Friday morning) 4:30am, Friday night – 2:30am  All this and a 7:00am return flight on Saturday morning will get you a splitting headache.

    If the course still sounds interesting I have some news for you – it rocks . . . but I was fortunate.  How?  Glad you asked.  (you did ask didn’t you?)  JP brings an incredible amount of passion for what he does and when I say passion I mean Love.  JP obviously loves coding.  He loves teaching.  He loves his wife and children.  I’d say he clearly loves his life.  His love for what he’s doing creates a safe environment for the students push themselves to the limit, to be challenged by the task and each other.   JP calls it ‘attacking the code without mercy’ and it’s only possible if everyone in the room buys into that atmosphere of trust.  It’s like in Peter Pan – JP’s attitude is the pixie dust – all you have to do is have your happy thoughts and we all can fly.  The group of guys in the Denver class did just that.  We all gave into the spirit JP tried to create and it made everything just work.  If even one of the students had decided to attack the others it wouldn’t have been so special.  I’m grateful to my fellow classmates for what they brought to our class – it was an awesome experience.  I can’t guarantee your classmates will be as cool as those in my class.

    Now we get to the worst part of all – after a long week of being taught, encouraged, and cajoled to be the best programmer and person you can be – it all ends.  You have to go back to the real world and the real life you left.  The ‘lost boys’ have to leave Neverland and grow up.  After 80+ hours you may have goals loftier than when you began and a list of things to learn next that would make most college students scream.  Unlike most classes, JP’s course isn’t a destination.  It isn’t the culmination of journey or a goal – it is the beginning of one.  And it is the days, weeks, months, and years that follow that will determine how valuable that beginning was – if Nothin But .Net was the beginning of your own ‘I love my life’ story.  This is my challenge now – to walk that path towards that programmer, that person I want to be and find my own way.  Thank you JP.

    As with all opinions and recommendations this one is based on my experience and things could change.  If you take JP’s course and don’t find the same love for coding and teaching coming from JP that I saw please let me know.  Somehow, I doubt that will happen.

    Pablo’s Topic of the Month – May 2009 Edition


    Have you ever read a blog post about TDD, Dependency Injection, or some other concept and thought, “Sounds great . . . if you work in an ivory tower, but I have to work with [insert your code-base here].”?  Or maybe you really like the idea but you have no clue how to start without beginning the project over?  If you answered yes then Pablo is going to make you smile because this month’s topic is Refactoring ‘Brownfield’ Projects.  Wikipedia has a fairly complete definition of Brownfield (http://en.wikipedia.org/wiki/Brownfield_(software_development)) but for our purposes you can consider any project that must use or take into consideration ‘legacy’ code a Brownfield project.  What is ‘legacy’ code?  Again, for Pablo this means any code that isn’t under test – including that lovely bit of code I just wrote . . . hmmm, I can’t wait to see what Pablo has this month.

    If you haven’t already, please consider subscribing to the Los Techies Main Feed so that you can see the various post from all the Los Techies bloggers.

    The main feed is here:  http://feeds.feedburner.com/lostechies

    As the month progresses you can expect posts on:

    We’ll update this post with the links for these topics as they are posted so stay tuned and Enjoy!

    Know Your Enemy


    Is it too late to make resolutions?  Oh well, I’ll make one anyway.

    I was listening to Eric’s talk on getting a legacy system under control (e.g. under test) and he mentioned a saying I’ve heard so many times before but this time it hit me differently: “Don’t allow Best to be the enemy of Better.”  I’ve had this beat into my head so much I usually don’t even consider the consequences of this statement as I code – it’s now a habit of thought.

    But as I sat there last night I realized a lot of us in the programming community, myself included, often fail to apply this concept to ourselves (our career/skills/idea of ourselves).  I believe this is part of the chasm Scott Bellware mentioned in a post about the gap between early adopters and mainstream developers.  As early adopters build the excitement around the concepts and ideas they’ve discovered the rest of us may build an artificial ‘best’ out of their ‘better’.  JP had a nice post on this idea and I’ll borrow a piece:

    Lots of developers are unhappy because they feel they are losing a comparison game that they are unfortunately playing. They are swamped with all of the information coming at them by people on “blogs, twitter, facebook, screencasts, podcasts”. They no sooner learn a new topic and then realize that one of the people they are following has already moved onto 15 new topics that they are now mastering. This can quickly become a very self defeating thing. Instead of savoring the journey, which is learning for them self, progressing at a pace that is comfortable to them, and one upping their personal abilities day after day; they become demoralized at the inability to “keep up”.

    By making someone else’s ‘better’ the basis for our ‘best’ we create a goal that may be both impossible to achieve and demoralizing.  I can’t tell you if you’re allowing your idea of Best to be the enemy of your ability to be better but I can say you’re not alone.  I can understand what many of the early adopters are saying but it takes me quite a bit longer to gain the ability to apply it.  Gabriel had a nice post on the process we all go through as we transition from our first exposure (level 1) to true understanding (level 6).  I can get to Level 2 on his scale fairly quickly with most things but getting from there to Level 5 or 6 takes me a lot longer than most of my Los Techies colleagues.  It took me many months to reach Level 5 with Lamda Expressions (ouch huh?).  That’s totally fine because no matter the time it took I achieved my ‘Better’ and it was a fun journey because I didn’t stress about it.

    So that’s my resolution – not to let anyone else’s ‘Better’ or ‘Best’ become the enemy of my Better.  My Better is mine and I’m going to enjoy achieving it.  Do you know your enemy?

    Hola Los Techies and Thanks!


    I was thrilled to be invited to join the Los Techies community.  I’ve been a fan-boy for some time and this is going to be fun.  No code in this post, so I’ll be brief.  I’ll mostly be focusing on how to apply some of the ideas the rest of the Los Techies gang blogs about in a less-than-ideal environment.  So, if you have to deal with legacy applications, the buy + build mentality, or tight budgets stay tuned and we’ll look at some ideas together.

     

    Thanks again for inviting me!

subscribe via RSS