Don’t Repeat Yourself: Keeping DRY with Dynamically-Generated Configs 🌞#
DRY – Don’t Repeat Yourself – is a principle of software development that cautions against repetitive software patterns and workflows. One of the major benefits of using hydra-zen’s config-creation functions is that they help us abide by the DRY principle. On the other hand, manually writing configs for your code will often leave you soaking WET (Writing Everything Twice).
To develop an intuition for these claims, let’s suppose that we want to configure the following class.
We’ll compare the processes of configuring DNN
using a YAML-file, using a hand-written dataclass, and using hydra_zen.builds()
.
Statically-Defined Configs are WET#
Manually writing a structured config for DNN
entails hard-coding its current import-path as a string as well as explicitly mirroring its signature:
from dataclasses import dataclass
@dataclass
class Builds_DNN:
input_size: int
output_size: int
layer_widths: tuple[int, ...] = (5, 10, 5)
device: str = "cpu"
_target_: str = "vision.model.DNN"
_target_: vision.model.DNN
input_size: ???
output_size: ???
layer_widths:
- 5
- 10
- 5
device: cpu
Doing this once isn’t so cumbersome, but consider that any time we modify DNN
by:
changing its location (e.g. move it to
vision.classifiers.DNN
)updating any of its parameters’ names, default values, or annotations
adding or removing a parameter to/from its signature
then we will need to mirror this change in our configuration as well. I hope you brought your towel, because things are getting WET 🌊.
Having to manually sync our configs with our code is not only tedious but it also creates a hot-spot for mistakes and bugs.
Generating Configs with builds
Keeps Us DRY#
We can stay nice and DRY by dynamically generating our configurations with builds()
.
Here we don’t need to worry about repeating ourselves in order to keep our config in sync with our code: the config (complete with type annotations and default values) is automatically and dynamically generated for us at runtime! 🌞
Additionally, any configured parameters that we do manually specify via
builds()
will be validated against the signature of DNN
as the config is being created. Thus typos and
mistakes will be caught fast and early - before we even launch our app.