InterSystems Caché Project Files and Folders
Hi, Community!
How do you store the source files of your Caché project? What is the directories structure? What are the benefits?
I prefer the following structure:
/cls/package/subpackage/class.cls /mac/package/routine.mac /int/package/routine.int /inc/macro.inc /dfi/folder/sample.pivot.dfi
Benefits:
- folders are packages.
- easy to understand what type of sources are in the project.
What is your approach?
Comments
cls/My/Deep/Class.cls
I don't think subdirectories should be applied for routines, originally routines aren't supposed to have submodules or subpackages and dots might be part of their name. Also if you need some complexity, you wouldn't prefer using routines but classes to keep things organized.
I DO NOT recommend using src, unless you want to mix both back-end and front-end code.
Or you want to keep the server code in a separated repository.
Here is a scaffolding based on React for better understanding.
my-app-project /
package.json
server
cls
mac
int
csp <- this is our build path, nothing should be added manually because everything is handle by the bundler.
scripts /
test.js
build.js
dev.js
config /
webpack.config.dev.js
webpack.config.prod.js
webpack.config.test.js
src /
components
Header
index.js
Header.js
HeaderSearchBar.js
Footer
index.js
Footer.js
FooterCopyright.js
AppContainer
index.js
AppContainer.js
containers
App.js
tests
components
Header
Header.js
HeaderSearchBar.js
Footer
Footer.js
FooterCopyright.js
AppContainer
index.js
AppContainer
You can use folders to separate both client and server codes inside the same project. You can even structure your project
using a monorepo approach if you want to keep multiple application modules together.
Now since React will be using webpack's hot module reloading along with webpack-dev-middleware that builds everything within the memory, your Caché server should only work following SPA conventions and providing consumable data.
There's a catch though, whenever the developer builds a new version (using webpack.config.prod), it's mandatory to delete the older bundle and import the project back to Caché to keep the source in sync on the server and the project.
Hi, Rubens!
Thank you for the wide answer, very interesting.
I agree with you on "no subfolders for routines" and separate folder for server-side code.
May I wonder what are you using as IDE (Studio? Atelier? Something else?) and how do you import/export your code with Caché.
I develop using a mix of Caché Studio with Visual Studio Code.
I use Visual Studio Code for dealing with front-end code, while using Caché Studio for back-end.
I don't use Caché Studio to edit static files.
I'm actually doing experiments using my Port library for managing export/import operations.
About how I keep the server code close to it's client counterpart is quite simple. By default Port exports project following the template /CacheProjects/{NAMESPACE}/{PROJECT}, so instead of depending on it, I overwrite that path to /my-repo/server.
From this point exported files will follow:
/my-repo/server/cls/My/Class.cls
/my-repo/server/cls/Another/Deep/Package/Whatever.cls
/my-repo/server/int/myroutine.int
/my-repo/server/mac/myroutine.mac
/my-repo/server/dfi/mydef.dfi
/my-repo/server/int/myinclude.inc
And so on, for every recognized Caché file format.
Now notice that I didn't said anything about static files. That's where a module bundler like Webpack is used to orchestrate the client-side workflow.
Now Caché only needs to send readable data back to the SPA (preferably JSON using %CSP.REST).
When the project repo reaches a milestone. I build a release to actually export the files to the path, like this:
/my-repo/server/web/app/bundle-[chunkhash].js
/my-repo/server/web/app/bundle-[chunkhash].css
Since [chunkhash] is unique per build, the consumer shouldn't have any issues with browser cache.
Now there's an issue: the bundled files still aren't inside the CSP folder, so I need to import the project back to Studio using Port.
Files are imported using UDL instead of XML. But Port always keep a project XML up-to-date along with the UDL code.
As you can see I can work with Caché code AND Client-code, alternating between both editors, thus keeping their own development scope, even though their code remain inside the same repo.
I think the most important part of source control file structure is mirroring package structure in Studio, since that is the view we spend the most time with. That said it looks something like this:
root/
Package1/
Class.cls
Class2.cls
Routine.mac
Include.inc
Package2/
Class.cls
Class2.cls
Routine.mac
Include.inc
Additionally:
- Web app should be stored in a separate repository.
- If there's docs/dictionaries/etc, then all sources should be in a /src folder instead of repository root.
- All libs/modules/etc should be moved into their separate repositories each and plugged in as a submodules.
- Builds, if any should not be stored in a repo but rather meta-managed (releases).
- Commit messages and granular commit history is one of the most helpful things when analysing project history, enforce commit message style (title is the most important i.e. PART/SUBPART - thing done in a commit).