Skip to content

Best Practices

Chr1Z edited this page Dec 16, 2024 · 3 revisions

General Information

In order to ensure the SCED code base maintains a high quality we have several best practices which should be followed for any submissions to the mod. These are broadly considered Soft or Hard requirements. Soft requirements are more like guidelines, while you may be asked to change something to follow them most reasonable exceptions will be allowed. Hard requirements are more stringent, and will require a strong reason for exceptions to be approved.

Please read these thoroughly, as they will be applied to any submissions during review.

Hard Requirements

Coding Style

Source files should use camel case with two-space indents.

Code should adhere to general good coding practices. Variables should be clearly named and locally scoped, functions should be small and focused, etc.

No Extraneous Files in PRs

TTS often applies odd rounding or other minor changes to objects, which can cause files to differ even if you haven't edited them. While TTSModManager has been designed to correct most of these, some may occasionally slip through. Any that do should be removed from commits so that PRs only contain files relevant to the change being made.

No Script Code on Objects

Source code should be in a separate file in the src/ tree, and not placed directly in the TTS objects. The Lua script on TTS objects should be nothing more than a require() statement which includes the code for that object.

Exception: Objects which share a script may place variables before the require() to provide configuration which the included file will use. Example

Exception: Objects which are included in downloadable campaigns are not currently integrated with the src/ tree, and must have code placed on them directly.

Cross-Object Access

Objects which access other objects should do so through our API pattern. Use of direct access including get/setVar(), get/setTable(), and call() are strongly discouraged as they create excessive coupling between objects, making future maintenance difficult.

Object API Pattern

Objects in TTS can access other objects, typically using something like this:

local someObj = getObjectByGUID("abc123")
someObj.call("someFunction")

This style is fragile, for a number of reasons:

  1. It creates excessive direct coupling between objects
  2. It's difficult to find everywhere that is referencing an object
  3. Changing the GUID becomes dangerous, as all uses must be updated

To avoid this, SCED uses an API pattern which provides a delegate to the object.

SomeObjApi.ttslua

do
 local someObjGuid = "abc123"
 local SomeObjApi = {}

 SomeObjApi.someFunction = function(val1, val2)
  return getObjectFromGUID(someObjGuid).call(
    "someFunction",
    { v1 = val1, v2 = val2 })
 end

 return SomeObjApi
end

MyObj.ttslua

local someObjApi = require("src/core/SomeObjApi")

function doSomethingElse()
 someObjApi.someFunction(5, 2)
end

While these are similar at the core, isolating access to SomeObj within the API removes the direct coupling, providing a control point for refactoring, limiting access, and single-point definition of other GUIDs.

API files should be require'd at the top of the file/scope and alphabetically sorted.

Soft Requirements

Limit Use of Tags

While tags are a very useful feature of TTS, excessive use can become unwieldy. Tags should be added only when they are the best (or only) choice for the feature being implemented.

Clone this wiki locally