Principle: Fulfill Requirements Where They Appear

2023-04-14

I think I'd like to document some of my programming principles that need more sensibility to be discovered.

This principle guides what to do when new requirements arise and can be applied at any level of your code, such as the module, function, or argument level. It basically states that the code to prepare data for an affordances of another part of your code should be as near as possible where the actual affordances appears.

This principle prevents you from changing existing code just because it's easier to do so, even though the requirements for the change appeared somewhere else.

An example:

I am currently building a generic node editor with Rust and egui. The node's are defined in the meta layer by meta::Nodes which define properties and their value editors. These meta::Node's are descriptions for the actual runtime::Nodes in the runtime layer of the editor.

One of the hardest things to implement, is to make parts of the graph reusable by treating them as functions. By adding special system nodes Outputs and Inputs a graph can be made into a function. This graph can be reused in other graphs.

For this to work, meta::Node's had to be generated dynamically. And now comes the issue. The layer that were generating the meta::Nodes returned references (&meta::Node) but the composed nodes needed to be Rc<meta::Node>, because they were generated in a component that needed to be stored as a RefCell, from which no &meta::Node references can be returned because of lifetime issue.

One solution to this problem is to wrap all the meta::Node returned from the meta layer into reference counted values. But this violates the stated principle, because the requirement came up in the runtime layer.

So I thought building a RcCache cache, that automatically converts and caches &meta::Node by cloning the values and integrated this into the runtime layer where both the original node types and the composite node types could be returned.

I am not sure if this cache survives future evolutions of the library I am building, but it is a interesting example of the stated principle.

For reference, here is the code for RcCache:

Not the topic of this post, but this code was created by GPT-4 with just a few prompts.

Have a nice day!