Well, you have just discovered an efficient path to CI/CD (Continuous Integration/Continuous Dev) again!! : )
We typically use the same model.
Data libraries. Then pure object libraries (PGMs...). And also in some cases pure "configuration libraries", specific libraries where parameters for external dependencies are expressed (imagine an api key for external service).
This allows for a nice composition. The whole set of libraries (system plus usr...) is named internally univocally logically (env name id).
We have a series of programs that manage the setting of libraries at startup or can be switched at runtime (i.e. a even a user can switch in a second the env to test some workflow).
Data in test env are copied automatically from prod daily or with desidered lag (so even a user that want to test something can have a playground with real data, not necessarily the dev).
In test envs test-pgm lib is put in front of prod-pgm lib with only the programs under testing and modifications.
Data of course is separated.
This model (exploiting the powerful LIBL resolution model) despite simple is pretty effective especially allows for very quick and accurate use of time and composition. For a classic company with home grown business logics is still IMHO an effective way. Especially appreciated if compared to some other Rube Goldberg machine solutions.
------------------------------
--ft
------------------------------