-
Notifications
You must be signed in to change notification settings - Fork 41
Best Practices
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.
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.
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.
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.
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.
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:
- It creates excessive direct coupling between objects
- It's difficult to find everywhere that is referencing an object
- 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
endMyObj.ttslua
local someObjApi = require("src/core/SomeObjApi")
function doSomethingElse()
someObjApi.someFunction(5, 2)
endWhile 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.
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.