Strike 3! Or is it?
What is a strike?
I pitched in the minors for 7 years. So I consider myself an "expert" in the knowledge of what is and isn't a "strike". However recently I challenged myself to a thought experiment. "What is the logically minimal definition of a strike?" That question made it obvious to me that knowing what a strike is and communicating that knowledge to someone else who has never heard of baseball are two different things. I, like most humans, tend to generalize concepts. And before this experiment I would have been happy to tell a naive fan that anytime the batter swings and misses it's a strike. Of course that description doesn't adequately describe a strike, rather is a over generalization of the concept. In many cases this is a good thing to do as it allows people to communicate broad strokes of understanding without delving into nuanced details until those situations arise. Unfortunately in software design, modeling the real world means modeling specifics which means you need an expert that knows the complex business rules, but can also explain complex rules comprehensively. Ultimately the intent of my thought experiment was to derive a simple methodology for asking experts the right questions to reveal their comprehensive understanding as a logical function. Enter Karnaugh maps.
It occurred to me that my best approach for explaining a strike to someone else would be to build the logical circuit that could map the know inputs to the know output. I defined my predicates as follows.
- Called Strike
- Swing & Miss
- Foul Ball
- 2 Strikes (Prior To The Pitch)
- Pitch Caught By Catcher
Strike Truth Table
Using the predicates that my expert (me) told me determined wether or not a pitch was a strike I was able to construct the truth table to the left.
I used a cool Karnaugh Map generation tool called Karma to build the following Karnaugh Map, it also derived the logical function based on it, and then refactored the logical function into the final logically minimal definition of a strike.
Translating this logical function back to it's English description shows the magic of Karnaugh Maps. If the umpire calls a strike, or the batter swings and misses, or if the batter fouls the ball off and there was less than two strikes or the catcher caught the ball, then it was a strike.
Success. We now have a way to explain what a strike is to anyone. Not so fast! We still have to get feedback from the expert. In this situation as in many real world examples the expert noticed a flaw in the logic. We did everything correctly, however the expert forgot to tell us one somewhat rare condition that could also lead to a strike. If a hitter were to bunt a ball foul with two strike, this also would result in a strike. But this is OK. Once we derived the logical function and the expert was able to evaluate it, he was able to say that all we needed to do was add one additional term to the group of predicates in parenthesis. F="attempted bunt". Our final truth function then is "C*(!D+E+F)+B+A". With this simple yet robust solution we can now be confident that our business logic is sound. Thanks Karnaugh.