Max Guernsey, I...'s profileMax Guernsey, IIIBlogLists Tools Help

Blog


    February 29

    Refactoring Data Seminar: March 25th, 2008

    I will be giving a free seminar on bringing Agility to the database world by enabling true refactoring on March 25th, 2008.  It takes place in Bellevue, WA and the venue was made available to us by Net Objectives.
    January 22

    And the Oscars officially mean:

    ...nothing!
     
    Amy Adams gets the shaft for what was, obviously, the most amazing performance of the year.
     
    Ellen Page gets a nomination for her robotic performance as Juno.
     
    The Acadamy Awards' credibility was already hanging by a thread.
    January 18

    DataConstructor

    So I've been working on a product for the last couple months.  It's called DataConstructor.  It makes agile database development possible.  Actually, it makes agile any-kind-of-data development possible.
     
    Check it out.  There's a free thirty-day trial, so you really have nothing to lose.
    August 01

    A New Word Is Born!

    Rebortion (n.)

    1. When a project is aborted, burned to the ground and, from its ashes arises a new (possibly cripled and slightly retarded) version of its former self that project has had a rebortion.

    Examples:

    "This project isn't delivering on expectations, I think it's time for a rebortion."

    "This is this project's fifth rebortion."

    May 09

    ScrumLLC

    Here is a very simple model I think would work quite nicely. If you're planning on starting an agile project, or developing a product, with Scrum think about taking the following steps:

    Form a subsidiary LLC (XYZ Scrum Team, LLC)

    1. This company should have an unusually short life-span, like 13 months.
    2. Capitalize XYZ Scrum Team, LLC mostly through a loan which stipulates that members cannot take distributions until that loan is repaid.
    3. Form an agreement with XYZ Scrum Team, LLC wherein all code written by that company is the sole property of the parent entity.
    4. Hire the the team members for XYZ Scrum Team, LLC and give them some interest. ("Working Members")
    5. Assign a "fair price" to each backlog item.
    6. Give the working members of XYZ Scrum Team, LLC control of the company.
    7. Allow XYZ Scrum Team, LLC to choose which backlog items it will be developed from a subset of the backlog items.
    8. For each item that is completed on time, pay the scrum team company the "fair price" determined above. Likewise: bill it for any expenses such as rent, power, and equipment.

    This incentivizes the working members of XYZ Scrum Team, LLC to do the most efficient thing

    ...in two ways:

    1. Reward: If XYZ Scrum Team, LLC is profitable and repays its initial loan, they can start taking distributions or cash out of the company.
    2. Punishment: XYZ Scrum Team, LLC still has a negative cash flow by the time it runs out of money then they no longer have a job.

    It also gives them a big picture perspective and enforces team accountability. They choose whether or not to make distributions (most of which go back to the parent entity), they choose which backlog items to deliver, and they deal with the consequences. If you get a good set of smart working members, they may be the first to recommend terminating the project or otherwise moving on to something more profitable.

    There are business advantages, too

    It separates the parent and child companies' interests nicely, and protects them from each other. If the parent company goes bankrupt, the child company can continue to function (assuming it can find another source of cash-flow, which should not be too difficult for a highly-functional Scrum team).

    Similarly, the parent company is not directly linked to those employees and, therefore, the risks associated with them are encapsulated within XYZ Scrum Team, LLC company. The worst case scenario is really that you write off the loan used to capitalize the company in the first place - which is a lot less risk than you might take otherwise.

    Most importantly: it brings the principle of cohesion into your corporate structure. Just as the cost of a virtual method call has dropped significantly in recent years, so has the cost of a subsidiary. Qualifying LLC's (to the best of my understanding) are taxed as partnerships and, hence, do not suffer the same C-taxation impediments that a corporation would (non-humans cannot own shares in S-corps).

    The result is better entity-structure

    Your "equity company" (the parent company) takes risk and reaps rewards based primarily on it's ability to assess, purchase, and market value whereas your Scrum team company takes risk and profits as a result of its ability to deliver quickly with quality.

    April 14

    Strengths & Weaknesses of .NET Exceptions

    "The outrages I have suffered today will not be soon forgotten!" - Stewie Griffen, Family Guy

    In the exceptions department, at least syntactically (in C#), .NET has something on Java but, all in all, I think it's down a few points.  One problem is that exceptions have to derive from the concrete class System.Exception.  The second and, in my opinion, bigger problem is that exceptions are not checked at compile time.

    The Good News

    As far as I know, Java does not support catching without specifying the type of, or defining a variable for, the exception being caught.  C# and, I think, VB.Net do.  Sound trivial?  It kind of is.  It's just a cleanliness issue... at best.  All it really gets you is the ability to avoid declaring the uneccessary.

    Instead of...

    try
    {
      // do something
    }
    catch (MissingMethodException exception)
    {
      // don't use exception
    }
    

    ...we can just do something like...

    try
    {
      // do something
    }
    catch (MissingMethodException)
    {

    // don't use exception }

    Instead of...

    try
    {
      // do something
    }
    catch (Exception)
    {
      // don't use exception
    }
    

    ...we get...

    try
    {
      // do something
    }
    catch (Exception)
    {
      // don't use exception
    }
    

    Wooptie-freakin'-do.  Still in the spirit of bone-throwing: Good job, guys.

    The Bad News

    The bad news is that the good news was trivial and there are real, significant weaknesses.  The fact that we have to place all exceptions somewhere in a single, monolithic hierarchy is a code-quality issue.  A lack of compile-time exception-checking defers discovery of problems.

    Come Join Us

    The inability to throw something that doesn't inherit from Exception is not that big a deal.  An abstract class can be used to hide implementation details as well as anything.  The real problem is that we can't catch based on anything other than a class.  All of the sudden, the "little code quality problem" caused by forcing all of our Exceptions into a unitary taxonomy has gotten a lot bigger.  This greatly limits our ability to catch categories of exceptions.

    Knowledge is... um... Liability?

    In Java you have to either catch an exception or declare that a particular method throws said exception.  This is not true in all cases - implementing certain interfaces renders an exception immune to compiler-checking - but it's a fairly minor, "opt-in" flaw.  When not circumvented, it provides developers with valuable feed back no later than compile-time... which is pretty early.

    In .NET, we don't get that.  Any exception can be thrown by any method.  This means that (realisticly) we can discover if an exception is properly caught no earlier than run-time.  The following is a list of cases in which I could see knowledge as a liability:

    • Temporal warfare based on the "plastic" model of sci-fi time-travel
    • Organized crime
    • Chasing a road runner off of a cliff

    Please note the position of "Programming" on that list.

    You Get The Platform You Deserve

    This is, in my opinion, the best part.  Oh so long ago I was talking with one of the people responsible for the design & development of .NET.  I asked them why they chose not to adopt a sort of "Catch or Specify" rule as existed in Java.  The reason was something along the lines of the following:

    Well.  If people are forced to specify anything they throw then they might be tempted to just put "throw System.Exception" everywhere.

    That's right.  In order to prevent the dregs of our industry from degrading the quality of their code, Microsoft did the obvious thing: it guaranteed that everyone's code is of equally low quality (in this respect).  It's all very Karl Marx.  How about this... let's take this to its natural conclusion:

    • To protect people from favoring inheritance over delegation, we should not allow delegation
    • To ensure that people don't break encapsulation, encapsulation should be eliminated
    • To prevent people from coupling two classes unintentionally, there should only be one class
    • In order to make sure people don't make something mutable when it should be read-only, let's get rid of the read-only modifiers

    In fact, I propose the following syntax for C# 4.0.  It is 100% guaranteed to ensure people don't make mistakes:

    return: causes the program to exit.

    ...and in VB.Net that would look like:

    Return: causes the program to exit.

    April 07

    Throw First, Please

    "No.  Dig up, stupid!" - Clancy Wiggum, The Simpsons

    One of my many, many pet peeves is when people do something like the following:

    if (condition)
    {
      do something
    }
    else
    {
      throw exception
    }
    

    It is a lot easier, cleaner, and more maintainable to do something like:

    if (!condition)
    {
      throw exception
    }
    do something
    

    Exceptions are about... Well... Exceptions

    Exceptions are more than just "an error handling mechanism."  They are a way of thinking.  Good code operates on a set of stipulations.  Cases that fall outside of those assumptions are not errors they are simply deviant circumstances requiring attention from a higher authority.

    The paradigm shift described above improves both cohesion and encapsulation and, out of that, falls out a secondary benefit: the ability to discover exceptional cases earlier.  With nested "if statements," assuming the problem is reasonably complex, it is usually difficult to fail as early as possible.  Doing so often leads to massive networks of nested if statements which are difficult to read or maintain.

    A Change in Thinking

    Shifting your mind set from handling multiple cases (if/else) to handling one case and "passing the buck" upward otherwise (if/throw) is not easy.  Most people won't just snap their fingers and shift gears.  Proper use of this technique requires the same delicate touch you might apply to static structure.  If you make the leap, though, your code will be a lot cleaner and more flexible.

    Better Encapsulation

    Consolidating decision making improves the Encapsulation or, at least, the potential for Encapsulation in your code.  With an if/else, you can refactor predication, but not the resulting branch, into its own method, as in the following:

    bool MeetsCondition(...)
    {
       return condition;
    }
    
    ...
    if (MeetsCondition(...))
    {
      do something
    }
    else
    {
      throw exception
    }
    

    Whereas with an if/throw, you can encapsulate both the decision and the branch.

    void EnsureConditionMet(...)
    {
      if (!condition)
      {
        throw exception
      }
    }
    
    ...
    EnsureConditionMet(...)
    
    do something
    

    The Encapsulation Bone's Connected to The Open-Closed Bone

    Another clear advantage is the ability to easily recognize new, and discard old, exceptional cases.  As your services gain popularity within a system, the set of circumstances in which they can be applied will flex a little.  Sometimes they flex inward - potentially eliminating the need for the exception.  Other times they flex outward - possibly adding an exceptional case.

    Being able to easily encapsulate both a decision and a branch allows us to do all sorts of neat things with it.  For instance: we could refactor our EnsureConditionMet method into a Strategy.  Once we've done that, we can move it into a Decorator, dissolve it into a Chain of Responsibility, Adapt it from some other component that already solves our problem, vary it with a Bridge, and so on...

    Discover Early

    Once you've broken out your exception raising technology, you get something else almost for free: early failure.  Every line of code that executes up to some point of completion carries with it a little risk.  If your exception discovery technology is broken out properly, it becomes easy to see when the earliest point at which a stipulation can be enforced: when you can provide the decider with all of the information it needs.  The sooner you throw, the less risk you incur on an task that will obviously not be finished and clean up after what has already been done.

    Conclusion

    Use exceptions the Chicago way: throw early, throw often.

    April 05

    Capacity to Deliver as a Currency

    "No one exceeds their potential. If they do it just means we didn't judge it accurately in the first place." - "Dr. Lamar" from "Gattaca"

    Basics

    For some reason people spend a lot of time cutting their own hamstrings.  They feel pressure to deliver so they work "harder," degrade code quality and, effective, borrow a feature from future releases at an exorbitant rate.

    Quality - and, I think, any kind of capacity for delivery - is a currency.  You can have more of it or less of it.  You can spend it to get a feature.  If properly deployed it can yield dividends.  If properly managed it starts to compound.  Sounds like a currency (or, maybe, an extremely liquid security), right?

    Let's go through a some models.  Now, like any good hypothesis pulled from one's gut (I leave it to the reader to guess what route it took), this entry relies on the principle of ceteris paribus.  Factors like people's ability to "learn while doing" are left out of the discussion but understood to have a real-life effect.

    We have two metrics: capacity to deliver and rate of delivery.  Capacity to deliver is an abstract measurement of all the things that allow a team to deliver functionality; skill, code quality, methodologies, processes, et cetera.  It is denoted by thick, green lines.  Rate of delivery is the amount of business value that is delivered in a period of time.  It will appear as a thick, red line.

    Good Manager/Bad Manager

    The simplest, and most prevalent, model for work is also the least likely to be realistic.  It is the notion that, ceteris paribus, capacity to deliver is constant and a good manager or project manager "rides" people to deliver.

    In this model, it is as though capacity to deliver is a ceiling from which the team's rate of delivery is suspended by springs.  A "good manager" constantly presses upward, compressing the springs and "squeezing a little more" out of his team.

    When a spring becomes exhausted, we call it "burn out."  The manager tries not to push too hard because he doesn't want to lose a good spring - after all: they may be pushing away from true potential, but they still keep things from falling apart.  To keep the spring coefficient from becoming zero, we periodically send springs on vacation or buy them lunch.

    In times of stress - times when the manager has just "gotta get something out the door" - he pushes harder on the rate of delivery - assuming that his springs will hold and that the green line (capacity to deliver) is constant.

    This doesn't seem to be a very realistic model and, fortunately, people are starting to realize it.  It seems to me, and to many others that the green line (capacity to deliver) is not a constant.  It can be manipulated and, actually, it is the most important thing too change.

    Capacity to Deliver as an Exhaustible Resource

    If we treat capacity to deliver software features as though it is mutable we get a different picture.  To do so, we have to redefine capacity to deliver.  Instead of being the absolute maximum a team might be able to do over some period of time, let's say it's the most a team could deliver in a sustainable way.

    In my experience, the red line and the green line appear to be covariant.  Each simultaneously affects how the other behaves but the rules aren't anywhere near as simple as the behavior of a spring.  I can't say I know all of the dynamics but I can say it's a lot more complicated than linear resistance.

    One thing I've noticed is that, when the red line is near the green line it pushes capacity to deliver away.  So, when the rate of delivery is just below capacity, capacity starts to go up.  When a team is delivering above capacity it starts to lose its ability to deliver in the future.

    Investing a Little

    Even this doesn't work like a spring, though.  It almost works like the opposite of a spring; as though there is a "sweet spot" where the pressure remains highest.  It seems like there is a focal point - at least when the rate of delivery is below capacity - where urgency provides incentive to invest surplus resources rather than squander them trolling the Internet for meaningless blog entries.  Beneath the sweet spot you will probably get nothing.

    No Drive

    Sometimes it's because people just don't feel a need to work.  Other times people need to work but there isn't enough context to do anything of value.  A worthless framework with high-code quality is still a worthless framework.

    One rule that's fairly obvious: the further above capacity you try to deliver, the more long term damage you do to your future abilities.  In other words, the rate of delivery presses down on capacity for delivery as though it were a weight proportional to the distance between the two.  Attempt to deliver too much, too quickly and you will break your product's or your team's back... or both.

    Slightly Over-Taxing vs. Oppressive Rates of Delivery

    Earlier, I mentioned that the two lines were covariant.  Capacity to deliver effects the rate of delivery in a couple of ways.  The true maximum rate of delivery is related to the capacity for delivery.   Once a team's capacity is sufficiently high, it will be able to achieve a sustainable velocity that is far greater than anything it could have done earlier - even at a "breakneck" pace.

    The Plastic Ceiling

    Sometimes what happens is the team is given an opportunity to improve its capabilities but, then, the pressure to deliver is increased (based on the "spring-loaded development" philosophy shown above).  When this happens, the results can be disastrous.  If the rate of delivery is cranked up too high (specifically: high enough to exceed the team's capacity), the team's capacity to deliver will start to degrade and all of the previously invested resources will go to waste.

    Management Turns Up the Heat

    The bottom line is this: Set realistic goals and focus on constant improvement.  If you do this, you will actually meet your goals in a sustainable way.  If you focus on short-term gains then all you get is a burst of apparent value with a massive, hidden liability.

    April 04

    Completeness vs. Agility

    "...but I'm so comfortable... too comfortable..." - Tool, "Undertow"

    NOTE: I use the word "Agility," in this entry, to refer to a hypothetical force that drives us to remain agile, nimble, or adaptable.  I am not referring to any specific Agile methodology.

    Recently, at the gig on which I am currently working, I was pairing with someone who is new to Design Patterns.  He was working his way through implementing the Composite pattern and doing a good job of it.

    At some point it was suggested that he wouldn't need to implement all of the methods on the composite class.  The reason for this was that, in the only known context for the composite, about half of the methods would be used.  To an extent, I could see the argument so I said nothing.

    The natural instinct, when building a software system, is to make it "complete."  That is: we try to add every feature that anyone might possibly need.  Later we find out which features were waste and which were necessary - assuming we deliver anything at all.  Agility drives us to mitigate waste by developing what is understood to be the most valuable thing first, then getting feedback on what's really important.

    So we can see how Agility and Completeness end up competing in a healthy way: the drive to complete things helps us implement the features to which we've already committed, and the drive to remain agile helps minimize the set of features to which we commit at any given point in time.  A very nice balance.

    This client of mine is working in a test-driven environment.  I don't just mean they write unit tests before they start to code - although they do that - I mean tests drive everything.  They write acceptance tests before they even start thinking about the units of code involved in a problem.  These tests are an excellent prototype for the environment in which all relevant classes will be instantiated.  It is very unlikely that leaving a class only partially implemented would end up being a problem as the acceptance tests will catch the problem before we call our software done.

    Still, I don't think that means we should leave a class half-implemented.  The same way that a feature is not "done" until it's done, it seems that a class should not be "done" until it fulfills its contract entirely.  I think that classes are atoms; they should always be whole and to divide one should be a considerable event with commensurate consequences.

    I propose that we separate in our minds the concepts of "completeness" and of "wholeness."  In so doing we can recognize that nothing intra-universal is ever really "complete" except (possibly) the universe, itself and then only in a grotesque sense.  Things can still be "whole," though.  For example: "I spent a whole dollar on that candy bar, yesterday."

    Wholeness could be a single force underneath which all the many flavors of "it's not done until it's done" could be united.  If we then recognize that Wholeness is not at odds with Agility the same way Completeness is, we end up with a nice, clean line for where to stop working on a thing.  Always favor Agility over Completeness when limiting scope, but never limit the scope in a way that would jeopardize Wholeness.

    Who knows?  It is possible that a deeper analysis would find that one remains more capable of responding to change if one keeps things whole.  In other words: Wholeness may be a part of Agility.  If that were true then I may have just wasted an hour.

    March 29

    The Zone of Distorted Complexity

    Man... that watch looks complex.

    This post is not, about the "intelligent design" hypothesis but it does reference arguments used in the surrounding culture war.

    Some people would make the following argument:

    1. If you find a watch in the woods, it is so complex that you would have to assume it was created by an intelligent being.
    2. Therefore life, being more complex than a watch, must be designed by an intelligent being.

    Many people accept this argument as legitimate.

    The argument first treats life (in the form of a forest) as though it is simple when compared to a timepiece.  Then, when it is convenient, the argument recognizes how much more complex than a machine life actually is.  It is a flagrantly self-contradictory argument that was mutated from something even more ridiculous and rhetorical: The assertion that you can tell something was intelligently designed merely by looking at it.

    In fact: a single bacterium from those hypothetical woods would be more complex than any man-made watch.  The watch has flat surfaces, refined substances, and gears with tines of regular sizes which are placed at regular intervals.  These are all simple things.  The reality is that it is the watch's simplicity that leads one to believe an intelligent being designed it, not its complexity.

    So why do so many people accept such an awesomely flawed argument as cannon?  One could argue that growing up in a religious household so distorted their perceptions of reality that they are emotionally incapable of recognizing how absurd such an argument is.  One would be both rash and wrong in so doing: growing up religious biases one's premises, not one's ability to perform logical analyses.

    I hypothesize that people regularly mistake complexity for simplicity (and visa-versa) by applying the following criteria:

    1. "If I cannot perceive the moving parts, it is simple."
    2. "If I can perceive the moving parts and I do not understand all of them, it is complex."
    3. "If I can perceive all of the moving parts and I understand them, it is simple."

    Were that to be true, it would create a "zone of distorted complexity" in rule #2.  In said zone, the complexity of a thing is perceived relative to the observer's understanding of that thing's domain rather than relative to the complexity of other similar things. 

    Continuing on the assumption that I am right - which is what I always do - there are two reasonable ways to handle someone who has trapped themselves in a zone of distorted complexity:

    1. Attempt to increase his understanding of the relevant domain.
    2. Attempt to increase his understanding of the fallacy in which he has trapped himself.

    The difference between these two is specificity.  Taking approach #1 addresses a specific lack of understanding.  Taking approach #2 addresses flawed thinking.

    Fortunately for me: I work in the computer industry which is a form of engineering.  Since engineering is man-made it tends to be - you guessed it - pretty simple up to the point where it bumps into a complex system such as the human body, an eco-system, or an economy.  As a result: fostering domain-knowledge is relatively easy.

    All I have to say is "Sucks to be you, biology teachers!"

    March 27

    I Had a Premonition: "This movie will suck."

    "I have become unstuck in time" - Billy Pilgrim, Slaughterhouse Five

    NO SPOILER ALERT: This movie spoils itself.

    Someone doing their laundry and dropping their kids off at school is not a basis for a movie, regardless of how the events are ordered.  Forward, backward, it doesn't matter: "Premonition" is still, for the most part, just a movie about that chick from "The Net" doing chores.  Rent "The Lake House" instead.

    March 23

    Cohesion: How Much is too Much?

    "...and I say your three cent titanium tax doesn't go too far enough!" - Jack Johnson, "Futurama"

    One of the most common complaints about "complexity" pertains to the principle of Cohesion.  The degree to which something is cohesive is the degree to which its parts are related.

    For instance, a method that checks an account balance and pets a kitty is not very cohesive unless that method happens to be part of the JamesBondVillain base class.  On the other hand, a method that checks an account balance and notifies the owner if their funds are running critically low would be pretty cohesive.

    It seems like a pretty good thing, right?  So how much is too much?  Let's take it to what some would call an "extreme:"

    Again we revisit our old friend: the Chain of Responsibility.  (Aside: the more I use this pattern the more I love it).  Many who implement this pattern do so by having a base class that encapsulates the decision as to whether or not the request should be passed down the chain.  Then they start adding derivatives of that class.

    That makes sense, right?  I mean, that's how it's implemented in "the" Design Patterns book.  Still... it seems like it contradicts a more fundamental tenet of the Design Patterns book: favoring delegation over inheritance.

    In most - though: not all - cases it seems that using a Strategy pattern to decouple the decision part from the handler part of a Chain of Responsibility could only serve you well down the line.  Yet, many claim that this is more difficult to understand than the so-called "canonical" form.

    The main arguments levied against cohesion are "readability" or "complexity."  I think this comes from a drive to understand all the pieces of a system before they can use any of it.  This, in turn, is driven by decades experience with brittle systems developed using, for all intents and purposes, ancient techniques.

    In a system where the code-quality is high, Encapsulation should protect you from the very implementation details that people feel the need to understand.  Good names will tell the consumer of a service what that service is.  The public interface of a type or method is all that should be required in order to use it.

    Then there's the "other" kind of system...  The framework built in a requirements-vacuum containing layer upon layer of needless complexity that served no purpose and was developed either "just in case" or to stave off boredom.  The system with cute names like "joesclass" and "Conn2DbWXmlCfg."  It will be difficult to wedge any kind of design pattern - simple, complex, or otherwise - into a system where it is that difficult to get your bearings.

    It appears to me that, when someone says, they think such structures are "too hard to understand," what they are really saying is one of the following:

    • "The quality of your system is too low to accommodate this sort of structure."
    • "I can't be bothered to evolve with the industry."

    If you often receive such complaints, address the problem empirically: write a little system and don't look at it for six months.  After it's been long enough that you don't remember much, go back and see how easy it is to add a feature to the system.  That should make it clear where the problem or problems lie.

    If you often complain about the "complexity" brought about by a system of many small classes rather than a few large ones, try to strike up a conversation about it.  Maybe things really are too complex.  Use concrete examples to make your argument and think carefully about the responses you get.

    In other words: the next time you are involved in a complaint about "too much cohesion" look for the fool.  If you can't find him, you're it.

    March 21

    One Piece at a Time

    "Little by little, one travels far" - J.R.R. Tolkien

    I see a lot of developers run into the same problem, over and over: they want to understand the "big picture" before they can get any work done.  They will spin their wheels trying to understand everything; writing and rewriting the same code or (hopefully) test over and over trying to get a lock on the "complete" or "true" nature of a thing.

    Allow me to preface the remainder of this entry by acknowledging that this phenomenon comes from the very best of motivations.  It happens to people who don't want to mess anything up.  Often, they are used to an environment where an incomplete understanding of the whole is synonymous with disaster or where they were able to "silo" themselves in a specific domain which they could easily grasp.

    To those whom this problem frequently haunts I would pose the following question: If you were putting together a jigsaw puzzle, how would you do it?

    Would you randomly try to force the pieces together until you had a puzzle?  I'd certainly hope not.  That would take an incredibly long time.  Then again, maybe I should hope you do because that means you think you are going to live long enough to put a puzzle together that way.

    Would you stare at the cover of the box and commit the image to memory, then put each piece exactly where it should be according to your recollection?  That seems like an equally ineffective extreme, to me.  Maybe you are smart enough to do it.  That would be pretty cool.  I'm not, though.

    It seems like most people assemble a puzzle incrementally.  Since most people aren't here to type, right now, I'll just describe how I do it.  I like to start with the border and work my way in, sometimes diverging from that process to capture "low-hanging fruit" such as highly recognizable objects or unique fields of color.  It is an empirical, intuitive, and flexible process that focuses on delivering a little piece of value at a time rather than following a "master plan."

    This analogy translates fairly well to software development; the one major difference being that not all of the pieces of the puzzle are even visible to you.  That difference can actually be an advantage, though, because it acts as a powerful force guiding your hand toward the next piece.

    If you have a problem to solve and a good acceptance test that proves when you're done, then you don't really need to understand all of the pieces up front.  The acceptance test would be the picture.  The fixtures for those tests are the border.  Your classes and methods stand in for the interior pieces.

    ...just start with the border and work your way in.

    Self-Referential Chains of Responsibility

    "Oh, you can't help that," said the Cat: "We're all mad here. I'm mad. You're mad."

    The Chain of Responsibility pattern is a powerful, flexible way of selecting the right handler for a request.  It has many uses but one that I'm really fond of is processing polymorphic descriptors. 

    Let's say we have a system of classes that, together, describe a criterion.  For instance: equals, greater than, and, and or.  From this we can build many different criteria.  As we develop our system we will - probably fairly early in the game - want to be able to convert a Criterion (the base interface for all the above criteria) into the where clause of a SQL select statement.

    Some might feel compelled to add a method to the Criterion interface to render it as SQL.  If you did that, each instance of Criterion would do two things (describe a criterion and render SQL).  Does that seem very cohesive?  Not really... it seems a lot better to break the task of converting making SQL out of a Criterion into its own class.

    Handling criteria like equals is probably fairly easy: once we know we have an equals Criterion, we just downcast, extract the relevant pieces and put them in the query string.  There may be challenges such as cross-platform parameterization but, for all intents and purposes, it's straightforward.

    Handling a Composite criterion such as and or or, however, is a little trickier.  Why?  Because this sort of composite is blind to the nature of its contents.  In other words: an and can contain another and, which can contain another and... and so on.  In addition to being able to contain itself, and and or can contain each other along with equals and greater than.

    While it is possible - though tedious - to handle such structures through brute force, as the number of types of criteria grows, a solution emerges as the clear winner: allowing elements in the Chain of Responsibility ("links") to refer back to the chain as a whole for decisions on how to handle the children of a composite.  We can save ourselves a little work by revising that solution to "Allow any link having a need to issue requests to the chain as a whole to do so."

    Here's the "tricky" part, though: most links that have a need to issue requests back to the chain need to send those requests to the head of the chain.  For instance, since both and and or could contain one another, the way their children are handled needs to be independent of their order in the chain.  Pointing back to the head of the chain ends up being a little stickier than we'd like.

    We could make it so that every link in the chain has a mutable Head property which, after the chain is constructed, is made up to date (or kept so as the chain is being constructed).  That's ugly, though.  We had a nice, clean, beautiful Chain of Responsibility that was (or should have been) totally immutable and we bashed it over the head with a mutable property that every link in the chain now has to support.  I don't know if you can live with that but I sure can't.

    What else can we do?  A Singleton, maybe?  No.  Singletons are evil and so are the people who use them.  I just can't bring myself to use any "pattern" which bears the "Marquis de Sade Seal of Approval."

    The problem goes away if we build a special kind of link whose only job is to be the head of the chain ("Head").  Ideally, we combine the Strategy and Factory patterns to keep the exact details of how our chain is built encapsulated from Head.  To do this, we would pass a factory in to the constructor of Head.  That factory has a single method that accepts a reference to a link (the head) and returns another link (the body).

    The constructor for Head passes a reference to itself in to the factory.  The factory then creates each link of the chain, passing in a reference to the Head as necessary.  Each link is given the opportunity to establish an immutable reference to the head of the chain.  When the factory returns a reference to the body of the Chain of Responsibility, Head can then set an immutable reference to the result.

    So, we're back to having an internally-consistent, immutable and (now) self-referential Chain of Responsibility.

    March 19

    Don't Touch My Privates!

    ...and stay away from my internals, too.

    A long time ago, I posed the question "Why would anyone use 'internal?'"  ...a very long time ago.  At the time I was only thinking of it as something that was weaker than "private."  Now, I realize that it is also stronger than "public."  I know... "doy."

    The fact is, though, that not a lot of people think about encapsulation at the assembly-level.  Considering the lean principles, we can see that "Optimize the Whole" and "Building Quality In," when combined, require a holistic view of quality.  That means quality at the method-, class-, assembly-, node-, and system-level, all tied together as one.

    Many of us have already come to the realization that encapsulation is a very powerful way of controlling (among other things) coupling.  What some may not yet have clued in on is that there are more forms of encapsulation than just making the right members of a class private.

    Good use of the various design patterns alone can encapsulate the consumers of a class from its existence if the consumer plays along.  I like to think of this as "voluntary" or "optional encapsulation."  If we go one step further and use an access modifier to hide the very existence of a type from the world, we can truly encapsulate it.

    Doing this ends up changing the role of the design patterns of which the encapsulated type is a part.  Instead of playing the role of minimizing bad coupling, they migrate to the role of facilitating good coupling.

    At my current gig, we came up with a pretty decent agreement.  Only factories and interfaces are exposed as public types; everything else remains encapsulated.  It's been working really well.  The forces it brings to bear are really constructive.  It puts into place a very strong dependency on interfaces that positively impacts the following:

    • Cohesion
    • Testability
    • Coupling (duh)
    • etc.

    I doubt I would ever go back.