Expand your SuiteScript skills in the Sustainable SuiteScript community for NetSuite developers.

Reader Response: SuiteScript Modular Architecture and Naming Conventions

Created: February 24, 2021

Following up on yesterday's source control question, reader Stephen also wrote in with several great questions of his own:

One change I've been working to implement is one UE/CLI script for every record type for any client of ours. The UE/CLI contains a bare minimum call into a module/library that does the heavy lifting. As we make more customizations, we just add libraries. I'm toying with the idea that "business logic" goes in the UE/CLI script and the nitty gritty details go in the module. So, a UE script would load in a module for each feature. I think this is what you were getting at with your comment, right?

This is precisely what I was getting at with my discussion of a modular software architecture. Entry points should be thin, meaning they do not contain much - if anything - in the way of processing, logic, or decision-making of any kind. Their only job is to delegate processing to an appropriate module (or set of modules) when a specific event is triggered. The work, the processing, the logic is contained in small, single-purpose modules.

I'd be interested to hear your thoughts on what constitutes "business logic" that should go into the entry point script and what constitutes the "nitty gritty" details that go in a module. Often I seem to end up with one function call in my entry point script and all the work in my library, but I feel like I should show more of what I'm doing in the Entry Point script. I'd also be happy to know pitfalls you see with this method of code organization too 😃.

First, we should clarify our terms; I typically call the nitty gritty details" the "business logic," so it seems we use that phrase differently. For me, Entry Points only exist to respond to events and delegate processing to appropriate modules based on the event. There might be a thin layer of conditionals to decide which module(s) get called, but other than that, entry points should never be interacting with the database or sending out HTTP requests or anything like that. All the real work should be encapsulated in smaller modules. Entry Point event handlers should read cleanly and clearly.

One drawback to combining many features in a single entry point occurs when you start breaking up your codebase into separate repositories and SDF projects. If you use an approach like I do where repositories and projects correspond to customization features, then you need to decide where these common entry points live, as one entry point may reference modules from multiple projects. Generally, I create a separate repository and project for the "NetSuite Core" for the account, and I use the dependencies in the manifest.xml in the Core project to reference any files from other projects. If you only have one repo and one SDF project for an entire account, then you don't need to worry about this.

Regarding naming conventions for files too, I'd be interested to hear your thoughts. Does it make more sense to name a script, for example, "Client Name Record Automations - SO - UE" or to change Client Name to My Company Name. I'm coming from the later and moving toward the former.

My convention for file names is:

  • clientAbbr_projectAbbr_recordType_scriptType_feature.js for entry points
  • clientAbbr_projectAbbr_feature_description.js for supporting modules

In practice that looks like:

  • sd_SMA_MR_Sync.js (Map/Reduce entry point for SMA sync process)
  • sd_SMA_Sync_Parsers.js (Parsing logic used by the Sync MR)

Generally, the name for the Script Record is similar, without the Client Abbreviation, with spaces instead of underscores: SMA MR Sync

My sincere thanks to both Stephen and Eric for sharing their questions.