See all glossary terms

Indirection

In a library, if you wanted a book, you could look through all the books until you find the one you want. But generally, you'll go through an index of all the books and find the one you want.
In programming, indirection is where instead of directly accessing a particular piece of data or resource, you access it indirectly through an intermediate step.
Anytime you need to jump from one location to another in your files, it's an added "level of indirection".
Here's code with some indirection. This is a button that sorts items by their value in a hypothetical inventory. The item's value is halved if the items has been used a lot.
@onready var button := $Button

func _ready() -> void:
	button.pressed.connect(_on_button_pressed)

## Returns the inventory item value. If the item is old, 
## it divides the value by two.
func get_item_value(item: Item) -> int:
	if item.usage > 0.5:
		return item.value / 2.0
	else:
		return item.value

## compares two items
func _compare_items(a: Item, b: Item) -> bool:
	return get_item_value(a) < get_item_value(b)

## sorts the inventory items by value
func _on_sort_button_pressed() -> void:
	inventory_items.sort_custom(
		_compare_items
	)
A lot of real code has much more indirection than that, spread accross multiple files.
Here is the same functionality, without indirection, using lambdas:
@onready var button := $Button

func _ready() -> void:
	button.pressed.connect(
		func() -> void:
			# sort the items
			inventory_items.sort_custom(
				func(a: Item, b: Item) -> bool:
					# we want the value divided by two if the item is old
					var value_a := item.value / 2.0 if item.usage > 0.5 else item.value
					var value_b := item.value / 2.0 if item.usage > 0.5 else item.value
					return value_a < value_b
			)
	)
A lot of programming advice recommends to enclose everything in functions, and to have a lot of indirection.
I don't think it's often the best advice. Yes, in the code above, there is some repetition of the same code twice.
But on the other hand, the code is self-contained, its usage clearer, and we can read it like a book, instead of jumping around. If we needed to change something, for example calculate the value differently for value_b, we could do so instantly.
Code with fewer indirection has a few key benefits:
  • it often requires less naming: we can use lambdas, or expressions
  • it often requires less documentation: we can see how its used from context
  • it is safer to change: you can change a few lines inside a function and confidently know you can't break anything, whereas changing an isolated piece of code is less certain.
  • it is easier to delete: Deleting lines is easy, but deleting an isolated piece of code is dangerous: what if something else was using it?
For that reason, at GDQuest we tend to consider indirection as an extra level of abstraction, that we only use when it really helps, after having given it due consideration.

See Also

Related terms in the Glossary