Terraform is supposed to let you write modular, reusable code. But because it's a limited DSL that lacks many "proper language" features (and occasionally breaks the rule of least-suprise). There are several major impediments to fully data-driven terraform. These ultimately result in copy/paste code, or tools like terragrunt which essentially wrap terraform and perform the copy/pasta behind your back by generating that code for you.
Some minor examples:
- calling a module multiple times using `for_each` to iterate over data works, except if the module contains a "provider" block
- if you are deploying two sets of resources by iterating over data, terraform can detect dependency cycles where there are not any