-
-
Notifications
You must be signed in to change notification settings - Fork 0
Style Guide
In all cases. it is best to write lots of small functions, rather than large functions or classes. This allows us to easily create test cases for each function. These functions can then be overridden and extended by projects to enable easy modifications to the base functionality. The functional paradigm also enables a data-oriented approach.
Functions should not rely on external state where possible, such as mutating variables outside of the function's scope (see Pure vs Impure Functions). The exception is when a function's purpose is to mutate state, such as a FLUX pattern receiver, a database mutation, or ECS interaction.
// CustomMathUtil.ts
// modules files must be named identitcally to their module, while lone function files must be named identically to the function they export
const addOne = (i: number) => {
return i++
}
// functions must be camelCase
const subtractOne = (i: number) => {
return i--
}
// modules must be CapitalCase
export const CustomMathUtil = {
addOne,
subOne
}
Testing
describe('CustomMathUtil', () => {
describe('addOne', () => {
// first test case
it('should add one', () => {
const result = addOne(1)
assert.equal(result, 2)
})
// second test case
it('should return NaN to non-number', () => {
const result = addOne(undefined!)
assert.equal(result, NaN)
})
})
})
An example of these stylings can be found as an initial draft at https://github.com/XRFoundation/XREngine/compare/network-action-receptors-follow-style-guide
export class User extends Service {
app: Application
docs: any
constructor(options: Partial<SequelizeServiceOptions>, app: Application) {
super(options)
this.app = app
}
async find(params: Params): Promise<any> {
if (!params.query) params.query = {}
const { action, $skip, $limit, search, ...query } = params.query!
const skip = $skip ? $skip : 0
const limit = $limit ? $limit : 10
delete query.search
if (action === 'friends') {
delete params.query.action
const loggedInUser = extractLoggedInUserFromParams(params)
const userResult = await (this.app.service('user') as any).Model.findAndCountAll({
offset: skip,
limit: limit,
order: [['name', 'ASC']],
include: [
{
model: (this.app.service('user-relationship') as any).Model,
where: {
relatedUserId: loggedInUser.id,
userRelationshipType: 'friend'
}
}
]
})
params.query.id = {
$in: userResult.rows.map((user) => user.id)
}
return super.find(params)
} else if (action === 'layer-users') {
delete params.query.action
const loggedInUser = extractLoggedInUserFromParams(params)
params.query.instanceId = params.query.instanceId || loggedInUser.instanceId || 'intentionalBadId'
return super.find(params)
}
// ...
}
}
becomes...
export const userServiceFindActionFriends = async (user: User, params: Params) => {
const skip = $skip ? $skip : 0
const limit = $limit ? $limit : 10
delete params.query.action
const loggedInUser = extractLoggedInUserFromParams(params)
const userResult = await (user.app.service('user') as any).Model.findAndCountAll({
offset: skip,
limit: limit,
order: [['name', 'ASC']],
include: [
{
model: (user.app.service('user-relationship') as any).Model,
where: {
relatedUserId: loggedInUser.id,
userRelationshipType: 'friend'
}
}
]
})
params.query.id = {
$in: userResult.rows.map((user) => user.id)
}
return Service.prototype.find.call(user, params)
}
export const userServiceFindActionLayerUsers = async (user: User, params: Params) => {
delete params.query.action
const loggedInUser = extractLoggedInUserFromParams(params)
params.query.instanceId = params.query.instanceId || loggedInUser.instanceId || 'intentionalBadId'
return Service.prototype.find.call(user, params)
}
export class User extends Service {
app: Application
docs: any
constructor(options: Partial<SequelizeServiceOptions>, app: Application) {
super(options)
this.app = app
}
async find(params: Params): Promise<any> {
if (!params.query) params.query = {}
const { action, $skip, $limit, search, ...query } = params.query!
delete query.search
if (action === 'friends') {
return userServiceFindActionFriends(this, params)
} else if (action === 'layer-users') {
return userServiceFindActionLayerUsers(this, params)
}
// ...
}
}