F#: Corrections over Treatments

Intro

I have reflected heavily over the past several weeks on domain design.

Specifically, I have posed the following question to myself:

When I discover a bug, why do I tend to treat the symptom/condition that the bug exposes instead of correcting the system’s design?

I decided to practice some F# by implementing a baseball game simulation. The code below appears to work. However, when I flushed out the logic for the functions and the various values that those functions left behind, I discovered a bug. Specifically, I exposed a bug in which a base can have more than one player assigned to it. I “treated” the advancePositions function as a result of my discovery. However, all I did was resolve the bug by treating the surface area that the bug was found in. What I didn’t do is correct the design such that the code cannot be compiled with the bug in it.

Here’s the code that results from me treating the function that I found the bug in:


(*Types*)
type Hitter = {
    Name:string
    LastPlay:Hit option
    Position:Position
}

and Position = | BatterUp
               | Base of Base
               | Bench

and Base =     | FirstBase
               | SecondBase
               | ThirdBase
               | HomePlate

and Hit =      | LuckyHit of Base
               | Single
               | Double
               | Tripple
               | HomeRun

(*Functions*)
let advancePositions hitType players =

    let update ``base`` player =
        match ``base`` with
        | FirstBase  -> { player with Position=Base SecondBase }
        | SecondBase -> { player with Position=Base ThirdBase }
        | ThirdBase  -> { player with Position=Base HomePlate }
        | HomePlate   -> { player with Position=Bench }

    let nextBase = function
        | FirstBase  -> SecondBase
        | SecondBase -> ThirdBase
        | ThirdBase  -> HomePlate
        | HomePlate   -> HomePlate

    let setBase = function
        | LuckyHit ``base`` -> ``base``
        | Single            -> SecondBase
        | Double            -> ThirdBase
        | Tripple | HomeRun -> HomePlate

    players |> List.map (fun player ->
                         match hitType with
                         | LuckyHit ``base`` -> player |> update (``base`` |> nextBase)
                         | hit               -> player |> update (setBase hit)
                        )

let hit play players hitter =

    let hit play hitter =
        match play with
        | LuckyHit ``base`` -> { hitter with Position = Base ``base``;   LastPlay=Some play }
        | Single            -> { hitter with Position = Base FirstBase;  LastPlay=Some play }
        | Double            -> { hitter with Position = Base SecondBase; LastPlay=Some play }
        | Tripple           -> { hitter with Position = Base ThirdBase;  LastPlay=Some play }
        | HomeRun           -> { hitter with Position = Base HomePlate;   LastPlay=Some play }

    (hitter |> hit play) :: (players |> advancePositions play)
    
(*Client*)
let scott =   { Name="Scott";   Position=BatterUp; LastPlay=None }
let brian =   { Name="Brian";   Position=BatterUp; LastPlay=None }
let cherice = { Name="Cherice"; Position=BatterUp; LastPlay=None }

let ``1stHit`` =  scott   |> hit Single []
let ``2ndHit`` =  brian   |> hit (LuckyHit SecondBase) ``1stHit``
let ``3rdHit`` =  cherice |> hit Double ``2ndHit``

let bases = ``3rdHit``

NOTE: Home plate can have multiple players assigned to it. Hence, on a given hit, multiple players can cross home plate.

Conclusion

In conclusion, I have reflected heavily over the past several weeks on domain design.
Specifically, I have posed the following question to myself:

When I discover a bug, why do I tend to treat the symptom/condition that the bug exposes instead of correcting the system’s design?

Thus, I discussed how I “treated” a function for a specific bug. In my next article, I will attempt to discuss how to “correct” the domain’s design such that code cannot even be compiled with the bug described.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: