What's the best way to organize my project so that I'm easily upgradable?

This is a general question about how one ought to organize large realistic projects that will have to be upgraded.


My consumer-facing daml-hub application has started to accumulate a lot of daml sub-projects for things like triggers, bootstrapping scripts, and automations. All told, there is one main sub-project containing the model, along with five or so sub-projects for triggers, automations, and integrations, e.g. user-admin-trigger, ledger-bootstrapper, stripe-integration. All of these are different daml projects having their own daml.yaml, because I do not want the main module to recompile every time I change a script. That would also cause me to have to run an upgrade script every time.

The Question(s)

But now that I’m contemplating upgrading my main module (entirely on ledger, since I already have contracts signed by customers), what should I do? Should duplicate the entire code-base, suffixing all the modules with V2 or something? And, second, what should I have done in anticipation of eventually needing to upgrade? Is it sufficient to rely on the versioning in daml.yaml, or should we always sub-module to a version, e.g. in the way DABL does with V2, etc.? Or, do I rely entirely on github to version the code, and simply import code from prior .dars solely for the upgrade scripts?


I personally prefix modules with something like V2 when upgrading. Eg MyApp.ModuleFoo.TemplateBar becomes MyApp.V2.ModuleFoo.TemplateBar. There is no technical requirement to do so, but it keeps things more human-readable. Otherwise the only distinction between V1 and V2 is the package hash.

Other than that, I’d think about the dependency graph of your model. If you upgrade a type, function, or template, you’ll also need to upgrade all descendants of that thing. So the main thing you can do when designing your application is trying to keep it fairly modular in the sense that you have units of code you can upgrade independently. One approach to this is to separate out data contracts from “rule” contracts so that you can change choices without needing to upgrade data.

Still, if you rwhole application revolves around manipulating an Asset template, and you need to change the data that’s stored on an Asset, there is currently no way around upgrading the entire application.