Skip to content

Managing the 16,777,217th Color

ADMIN | 01-03-2012

Managing the 16,777,217th Color

Hexagon pattern 1

Here’s a quick poll:  How many of you have figured out by now that 16,777,217 = 2^24+1, and that the "24" refers to the 3 RGB bytes in RGBA32?

An alternate title I considered for this post was "NoColor is a color", which would have been an inside joke for people who go to science fiction conventions.  Considering the audience, I decided to stick with the computer science reference :)

So, what am I talking about?  The fact that, for 24-bit RGB colors, there are actually 2^24+1 possible states, since the absence of color is itself a state.  This in turn causes problems because it’s very difficult to jam 2^24+1 states into 24 bits.  The more subtle problem here is that people often aren’t thinking about the extra state when they write their code, which can lead to "Happy Path" algorithms.  So the question is, "How do we provide an interface to customers that manages the NoColor issue in the best way possible".

Let me give a concrete example.  In our CGM product, we provide the ability to attach "properties" (such as color) to geometric objects – basically we provide SetColor and GetColor methods.  If no color is present, then the object takes on the color of its parent object (or the default color if it is a root object).  The problem we had to deal with was how GetColor should indicate the absence of color.  More precisely, what should the signature of GetRed be, and what should it do when color is absent?

First, the evil answer: int GetRed() returns a “magic (invalid) value” such as -1 when no color is set:

The reason this is evil is that the server (the Color1 class) is intentionally returning an invalid result, and relying on the person writing the client code to remember he needs to check for a special state, then go down a different code branch in that case.  I remember reading somewhere (but can’t find the reference) the "Tiger Trap" principle of interface design: that using the interface correctly should be like a tiger trap – consumers of the interface naturally fall into it.  With this interface choice, the tiger trap is in the direction of using the interface incorrectly.  An insidious variation on this design which might even be worse is to return a valid value for red in the NoColor case.  The reason this might be worse is that an invalid value can be detected by a contract check (in DisplayRedValue() in the example).  A valid (but arbitrary) value is undetectable, and can lead to weird results that are difficult to track down.

Next, the answer from my last post:  create a Nullable<T> template class and have the GetColor query on an object return a Nullable<Color>:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

There are several nice things about this approach:

  • The color class is now responsible for only 2^24 states – the NoColor state is managed by the Nullable class.
  • The Nullable class is designed for exactly this situation, so the approach is intuitive.
  • The tiger trap is now in the correct direction –the compiler won’t let the customer call GetRed() on a Nullable<Color>.

In fact, this is the approach that we use our sample scripting application for CGM – the javascript objects returned by GetColor() wrap a Nullable<Color> object. 

Although the Nullable approach is appropriate in certain circumstances, it still has a drawback: the client still needs to write an if statement when actually getting the RGB values.  This problem is solved by the last approach: pass the RGB values by reference, and don’t change them if the color is unset:

 

 

 

 

 

 

 

 

 

The nice thing about this interface is that it caters to the client’s workflow.  Basically, the client calculates the RGB values that will be used if the color is unset (typically by looking at parent objects and/or the default color).  The client then calls GetRGB – if the color is unset, then the previously calculated colors are left alone, otherwise they’re overridden.  This is the interface that we chose to use for color (and other, similar) properties in our CGM product.

We have found this signature idiom to be really useful in a lot of places.  For example, it’s a natural fit for a chain-of-responsibility pattern:

 

 

 

 

(Yes, I know I could reduce this to a single line, but I’m conservative about these things J )  I’m sure many of you are already using this one in your code, but for those of you that aren’t, I hope you find it useful as well.

One last thing: if anyone out there knows the correct tiger-trap reference could you please post it in a reply?  I’d really like to track it down for proper attribution.

You might also like...

5 Min read
CGM Modeler
Software components are like the stage crew at a big concert performance: the audience doesn’t see them, but their...
Application Lifecycle Management Flow
4 Min read
CGM Modeler
When you hear the term, Application Lifecycle Management (ALM), you likely think about the process that a software...
8 Min read
CGM Modeler
What is Computer Aided Manufacturing The CAM Market Who Uses CAM Software? Trends in CAM What do CAM Software...
9 Min read
CGM Modeler
SLS in Additive Manufacturing is used to convert 3D CAD designs into physical parts, in a matter of hours.
8 Min read
CGM Modeler
There’s a lot of confusion around what the terms additive manufacturing and 3D printing mean.
5 Min read
CGM Modeler
Take a fresh, new sheet of paper, and fold it in half, like you’re making a paper airplane. Place the folded paper on...
6 Min read
CGM Modeler
Table of Contents Simulation in CAD Who Uses Simulation Modeling? Key Benefits of Simulation Modeling Challenges in...
8 Min read
CGM Modeler
What do you do? What Exactly is FEM? What You Need to Know About Choosing a FEM Modeler FEM and Partial Differential...
5 Min read
CGM Modeler
Computational Fluid Dynamics (CFD) is a type of analysis that provides insight into solving complex problems, and...
2 Min read
CGM Modeler
WRL files are an extension of the Virtual Reality Modeling Language (VRML) format . VRML file types enable browser...
Voxel model example
3 Min read
CGM Modeler
Voxels are to 3D what pixels are to 2D. Firstly -- let’s examine what pixels actually are. Everything you see on your...
Point_cloud_torus
2 Min read
CGM Modeler
Point-cloud modeling is typically used in the process of 3D scanning objects. Rather than defining surfaces through...
Polygonal Modeling
2 Min read
CGM Modeler
Polygonal (or polyhedral) modeling is the most common type of modeling for video games and animation studios. This type...
aerodynamics-CFD
9 Min read
CGM Modeler
Computational fluid dynamics (CFD) is a science that uses data structures to solve issues of fluid flow -- like...
BREP Model example
2 Min read
CGM Modeler
BRep modeling, or Boundary Representation modeling, is, in CAD applications, the most common type of modeling. BRep is...
Feature Recognition Zoomed
5 Min read
CGM Modeler
IN THIS ARTICLE: What is FEA (Finite Element Analysis) Principles of Finite Element Analysis and Simulation Software A...
CAD System Components
4 Min read
CGM Modeler
Effective computer-aided design (CAD) and computer-aided manufacturing (CAM) programs include the following main...
3 Min read
CGM Modeler
The 2017 1.1 release of Spatial’s CGM™ Core Modeler improves the robustness of its feature recognition capabilities by...