Logic tables

When you have one condition dependent on several other variable conditions, it helps to create a logic table in order to keep your code clean and race-condition free.
The conventional definition of a logic (or truth) table is just a grid defining your inputs and expected outputs. For the purposes of programming, your logic table doesn't need to be a grid that grows based on the number of permutations, it could be a sequence of conditionals, but either way, you should represent your inputs and outputs in a single function.

Example:

In A In B Out C
true true ready
false true loading
true false loading
false false inactive

Or:

if (A && B) 
	C = ready
else if (A || B)
	C = loading
else
	C = inactive

Whenever A or B changes, C may be a different value. Therefore you would need to be absolutely sure that you know every situation these dependent variables are changing. The easiest way to do this is to make the variable unchangeable unless it's through a single method. It would be difficult to maintain your code if every time your logic table changed you have to track down every situation the variable is set.

setA(bool value)
	A = value
	refreshC();
 
setB(bool value)
	B = value
	refreshC();
 
refreshC()
	if (A && B) 
		C = ready
	else if (A || B)
		C = loading
	else
		C = inactive

The exact implementation of this may differ, for example, instead of calling refreshC() in the setters, you might want to use data binding, but the important part of this is to have the resolution of the dependent variable in a single place.

To expound on this, here is a real world example showing how easy it is to paint yourself in a corner when not using the technique of using logic tables.
We'll start creating a simple button, showing two paths of coding, one with a logic table, one without.

(1 independent variable)
Without logic table:

	OnMouseOver:
		state = over
	OnMouseOut:
		state = up

With logic table:

	OnMouseOver:
		over = true
		refreshState()
	OnMouseOut:
		over = false
		refreshState()
	refreshState:
		if (over) state = over
		else state = up

So far using the logic table is more complicated, but we only have one independent variable. What happens when we start adding complexity? Let's add a mouse down state.

(2 independent variables)
Without logic table:

	OnMouseOver:
		over = true
		state = over
	OnMouseOut:
		over = false
		state = up
	OnMouseDown:
		state = down
	OnMouseUp:
		if (over) state = over
		else state = up

With logic table:

	OnMouseOver:
		over = true
		refreshState()
	OnMouseOut:
		over = false
		refreshState()
	OnMouseDown:
		down = true
		refreshState()
	OnMouseUp:
		down = false
		refreshState()
	refreshState:
		if (down) 
			state = down
		else		
			if (over) state = over
			else state = up

So far we have two independent variables, and while the code doesn't look too bad yet, we're starting to get into potential race conditions. What happens when the user presses down on the button and then drags outside the button? Down, out, over, then up? The logic table is already making it more clear what state we're supposed to be in at all times.

We might not have known it at the time, but there are yet more feature requests for this button. We not only need to change states on over and down, but people are demanding selected and disabled states. How do the two approaches look after 4 independent variables?

(4 independent variables)
Without logic table:

	OnMouseOver:
		over = true
		if (enabled) 
			if (selected)
				state = selectedOver
			else
				state = over
	OnMouseOut:
		over = false
		if (enabled) 
			if (selected)
				state = selectedUp
			else
				state = up
	OnMouseDown:
		down = true
		if (enabled) 
			if (selected)
				state = selectedDown
			else
				state = down
	OnMouseUp:
		down = false
		if (enabled) 
			if (selected)
				if (over) state = selectedOver
				else state = selectedUp
			else
				state = over
	Select:
		selected = true
		if (enabled)
			if (down) 
				state = selectedDown
			else
				if (over) state = selectedOver
				else state = selectedUp
	Unselect:
		if (down) 
			state = down
		else		
			if (over) state = over
			else state = up
 
	Enable:
		enabled = true
		if (selected)
			if (down) 
				state = selectedDown
			else
				if (over) state = selectedOver
				else state = selectedUp
		else
			if (down) 
				state = down
			else		
				if (over) state = over
				else state = up
	Disable:
		state = disabled

With logic table:

	OnMouseOver:
		over = true
		refreshState()
	OnMouseOut:
		over = false
		refreshState()
	OnMouseDown:
		down = true
		refreshState()
	OnMouseUp:
		down = false
		refreshState()
	Select:
		selected = true
		refreshState()
	Unselect:
		selected = false
		refreshState()
	Enable:
		enabled = true
		refreshState()
	Disable:
		enabled = false
		refreshState()
 
	refreshState:
		if (enabled)
			if (selected)
				if (down) 
					state = selectedDown
				else
					if (over) state = selectedOver
					else state = selectedUp
			else
				if (down) 
					state = down
				else		
					if (over) state = over
					else state = up
		else
			state = disabled

This is a good analogy to a frog in a pot of slowly heating water.
With the logic table, there was a single point to update, it's very clear how it's supposed to work, and will inevitably be much more stable. Without a logic table, trying to update your dependent variables ad-hoc will result in race conditions and less-maintainable code.