Open benloh opened 2 years ago
In GitLab by @daveseah on May 9, 2022, 14:23
comment from ben from slack re appcore to datacore connections (from a discussion on how a datacore API operates relative to something that uses it like an appcore)
I think there were three levels of constraints for datacore that are somewhat related:
In GitLab by @daveseah on May 9, 2022, 15:23
Another area: Typescript Conventions
t-name.d.ts
and are we using it correctly? I think these are autoloader definitions but they aren't set up correctly in our toolchain so we import them directly.t-name.d.ts
is a map of all the related system concepts in one subsystem. For example, t-script.d.ts
is everything related to the transpiler's scripting, and t-assets.d.ts
is everything related to the asset management/asset loader operations.We use a few prefixes in a general way that is from the typescript documentation but maybe not specific enough as we are with our variable and function naming.
T
prefix is used for any general type declaration. I
prefix is used for general interface declarations, which are a substitute for "base classes" and "inheritance" in C++ like languages.class SubsysObject
declaration can use both T and I declarations, and is used to represent the object type.TSubsys
prefix is used to identify groups of related types. Example: TSMCProgram
is a type for the transpiler+execution engine which runs our ad-hoc "Stack Machine Code"E
prefix is used for any enum declarationsThere are some special cases:
TPrefix
are used for parameters. IPrefix
(interfaces) can do something similar but are only for classes that implement
them.class SubsysObject implements IPrefix
gives you the choice of defining properties/methods on either IPrefix
or SubsysObject
. In general though you should use the class declaration itself when you mean the object, and the interface for when you are expecting some base class operations ONLY. Typescript Tricks worth noting:
EBundleType.BLUEPRINT
enum MyEnum { A, B, C }
type enumValues = keyof typeof MyEnum
type ObjectWithKeysOfEnumAsKeys = { [key in enumValues]: string }
Object.values(EBundleType).includes('blueprints)
which works because typescript converts EBundleType
into an object.symbolType: keyof TSymbolData
TAssetType = 'sprites' | 'sounds' | 'projects'
, and you can specify this similarly as { [K in TAssetType]:any }
which restricts the properties to the possible type values onlytype enumValues = keyof typeof MyEnum
(see keyof vs keyof typeof)In GitLab by @daveseah on Jun 8, 2022, 08:00
Yet another area: React Handler (and UI handlers in general)
An issue I see is that there is no distinction made between what is a user interface event handler (aka code that routes an Event object) versus application logic (code directly receives data to perform some application operation) versus gui logic (code that directly receives an event or data to change the state of the gui without changing any application data). These are three distinct operations, and our code should show this distinction.
Example below is the fragment of code to discuss
<button type="button" onClick={SaveSlot}>
function SaveSlot(e) {
WIZCORE.SaveSlotLineScript(e);
}
export function SaveSlotLineScript(e) {
const {
slots_linescript,
script_tokens,
sel_linenum
} = STORE.State();
const lineIdx = CHECK.OffsetLineNum(sel_linenum, 'sub'); // 1-based
script_tokens.splice(lineIdx, 1, slots_linescript);
STORE.SendState({ script_tokens });
}
quick notes:
onClick
prop is binding to another function definition and not explicitly passing the event. It's important to show that the event is being passed because this makes it clearer that it's a UI event handler. Better written as onClick={event=>SaveSlot(event)}
even though it is more verbose. This also has the effect of (1) binding the containing variable scope to the arrow function explicitly, which is helpful in class components that are not using .bind()
explicitly and (2) you can tack on additional parameters other than just event
to reuse the same handler but with different parameters.
function SaveSlot(e)
is not doing very much other than redirecting to another call. It's not even unpacking data from the event (which is also unidentified). It's just code noise and it's passing UIEvent to WIZCORE directly to perform a data operation. This is conflating two concerns into one.
export function SaveSlotLineScript(e)
in WIZCORE doesn't even use the event that's passed (and it's still called e
and untyped). It's performing a pure data operation based on internal state.
quick outline:
Sri is codifying the past 7 years of our programming code style in one place so they can assign fancy numbers to them or something. Plus they keep seeing these issues pop up over and over, so this indicates that maybe they are not clearly stated.
GENERAL CONVERSIONS
export function FName
toexport { FName }
at the end of the module, so it's easier to see everything at the endtranspiler-v2
is an example of thisimport
statements to the path alias style. The available path aliases (like 'modules' and 'script') are definedgem-srv.tsconfig.json
/** API: description
for any code that is an API method that's being exported. Everything else should usem_FunctionName
syntax, and also be noted as/** support: desc
/**
opener.DBG
flag or commenting them out.BONUS: GENERAL CONVENTIONS
import * as MODNAME from ...
, notimport { MethodA } from ...
function m_SupportMethodName ()
SOMETHING_DICT
m_variable_name
function (aVar, bSomeOtherVar)
snake_case_var
f_function_name
oru_function_name
(u stands for utility)BONUS: STYLE CONVENTIONS LOOSELY KEPT
GetTypeOfResult(param)
Get
as a prefixVerbTheThing()
PromiseTypeOfResult
WIP: DATA AND COMMAND ABSTRACTIONS
A module or class API is a collection of methods that are designed to communicate its conceptual model of use. In object-oriented terms, I think of this as figuring out:
Knowing that, you can then design the API so the following is clear and consistent, and that its scope of responsibility continues to be clear:
This is all very abstract, so we need to come up with canonical STEP-related concepts and patterns that are already in use.