::use(
box/module/statistics/time_series
.
)
$ACF(AirPassengers) time_series
[1] 1.0000000 0.9480473 0.8755748 0.8066812 0.7526254 0.7137700 0.6817336
[8] 0.6629044 0.6556105 0.6709483 0.7027199
One of the good parts about {box} package is it allows accessing deep nested scripts / folders in any depth as modules.
Building on what you learned in the previous section about creating modules from subfolders, {box} doesn’t limit you to just one level of nesting. You can organize your code into multiple layers of directories, creating a hierarchical structure that makes sense for your project’s complexity and organization needs.
Let’s update {./module} folder from Chapter 3.1, by updating (or just copy and paste the source code of {./module} in GitHub) matrix_ops.r
to store functions that rewrites *
for matrix multiplication and overrides ^
where a specific value, ^-1
, implies the inverse of the matrix, and tables.r
to store functions for displaying tables in R REPL, and extending the {./module/statistics} subfolder by adding another level of organization, e.g. you want to add statistical model utilities organized by model type, saved as {./module/statistics/models}* subfolder.
module/
├── __init__.r
├── convert.r
├── hello_world.r
├── matrix_ops.r # <------------- Under root **{./module}** folder
├── not_func.r
├── tables.r # <------------- Under root **{./module}** folder
└── statistics/
├── __init__.r
├── cor.r
├── corrr.r
├── time_series.r
└── models/ # <------------- Subfolder within subfolder
├── __init__.r
├── linear.r
├── logistic.r
└── baseline_logit.r
In this structure, {./module/statistics/models}* is nested two levels deep from the root {./module} folder. Each directory still requires its own __init__.r
file to be recognized as a module.
Remember that every folder you want to treat as a module must contain an __init__.r
file, regardless of its depth in the folder hierarchy.
Under {./module/statistics/models}* subfolder, place this in __init__.r
file:
#' @export
::use(
box/linear,
./logistic,
./baseline_logit
. )
And since we are adding another module within {./module/statistics}, update its __init__.r
initialization file:
#' @export
::use(
box/cor,
./corrr,
./time_series,
./models
. )
You can access these deeply nested modules using the same syntax patterns you’ve already learned in the previous chapter, just with longer paths:
::use(
box/module/statistics/time_series
.
)
$ACF(AirPassengers) time_series
[1] 1.0000000 0.9480473 0.8755748 0.8066812 0.7526254 0.7137700 0.6817336
[8] 0.6629044 0.6556105 0.6709483 0.7027199
Or you can use the parent module and traverse through the hierarchy:
# Access through the parent module
::use(
boxmd = ./module
)
# Navigate through the nested structure
$statistics$time_series$ACF(AirPassengers) md
[1] 1.0000000 0.9480473 0.8755748 0.8066812 0.7526254 0.7137700 0.6817336
[8] 0.6629044 0.6556105 0.6709483 0.7027199
While {box} allows you to nest modules at any depth, here are some of my software engineering principles to consider when organizing your code:
Keep it reasonable: Deeply nested structures can make navigation more complex. Most projects benefit from a relatively flat hierarchy, though the optimal depth depends on your project’s size and complexity.
Organize by functionality: Group related functions in a way that makes sense for your workflow. For example, keeping all model-related functions under {./module/statistics/models}, organized by algorithm type.
Use meaningful names: Choose folder names that clearly indicate their contents, making it easier to locate specific functionality.
Document your structure: A README file or comments explaining your module organization can help collaborators (and future you) understand the project layout.
Be mindful with ../
: Frequent use of parent directory navigation might suggest opportunities to reorganize your structure.
There’s no strict rule about module depth. The {box} package itself doesn’t impose limitations on nesting levels. Organize your modules in whatever way makes your code most maintainable and understandable for your specific project needs.