dsriseah / ursys

an opinionated javascript library for prototyping realtime web apps
1 stars 2 forks source link

Codestyle: Sri Coding Patterns #9

Open dsriseah opened 4 months ago

dsriseah commented 4 months ago

An issue for sharing and debating coding patterns

dsriseah commented 4 months ago

Logging in Node

I like to use fancy padded output, using a pattern like this:

const DBG = false;
const PR = typeof process !== 'undefined' ? 'EndPoint'.padEnd(13) : 'EndPoint:';
const LOG = (...args) => DBG && console.log(PR, ...args);
LOG('hello');

and

import { PR } from '@ursys/core';
const LOG = PR('HTTP', 'TagBlue');
LOG('hello);

which produces output like: image

Logging in Browser

In browserclients console.log always reports the line where it's used. There might be a .bind(console.log) that works, or I can use my PROMPT utility which uses this pattern:

const PR = UR.ConsoleStyler('MYMOD','tagRed');
console.log(...PR('hello',1, 2));

ConsoleStyler returns a function that destructures into the css syntax to produce this (in Chrome)

image

It looks a bit different in Firefox and Safari.

dsriseah commented 4 months ago

Functions returning data in object

When it's possible for a function to return an error and I don't want to use try/catch, I define a return object type that can either be an object with error property or a regular successful return

type TReturn = { error?:string, a?:number, b?:number };

function ReturnSomething( id:number ) : TReturn {
  const item = LookupItemById(id);
  if (item===undefined) return { error:'invalid item id' };
  const { day, month } = item;
  return { day, month };
}

// use
const { error, a, b } = ReturnSomething(id);
if (error) {
  console.log('uh oh, error', error);
} else { 
  .. do what you need
}
dsriseah commented 4 months ago

Function returning array OR single item

This pattern I have used here and there, but I'm not sure it's a good idea. If a collection operation returns an array with a single object, then it's removed from the array and returned.

function NormalizeData(data: NP_Data): NP_Data {
  if (Array.isArray(data) && data.length == 1) return data[0];
  return data;
}

// use
const selected = NormalizeData(GetSelection());

In the above case I don't think it's a good idea...I would probably just want to assume that it's always an array, even if it's empty. That's an easy conditional check rather than using Array.isArray()

There's a place in URSYS where this is used when implementing network messaging. Since there can be multiple message handlers, the dispatcher will return an array of responses. However, it's not typical to expected an array of results.

retData = NormalizeData(retData);
pkt.setData(retData); // returns either a single object or array of objects

This might be handled just at the API level, describing the return type.

Also, this can be reinforced with the naming convention of the function

dsriseah commented 4 months ago

Functions accepting object parameters

I like to limit the number of parameters passed to functions from 0 to 2; if I need more, then I use a parameter object because I can define it before the function call and be explicit about it in a more readable way.

type TParam = { a:number, b:number };

function DoSomethingToID( id:number, opt: TParam ) {
  const {  a, b }  = opt || {};
}

// use
const options = {
  a: 10, // dimension x
  b: 20 // dimension y
}
DoSomethingToId(id, options);
dsriseah commented 4 months ago

Paths

[!TIP] TLDR

  • paths never have a trailing slash
  • directories are paths that have a trailing slash added
  • files are paths that do not end with a trailing slash
  • filenames do not have slashes anywhere in them (with some exceptions

I make distinction between a directory, a path, and a file. In practical terms, where do you put the slashes?

Known Rules:

Implied Rules:

Derived Rules:

Therefore:

To construct a compound path:

`${absPath}/${relPath}/${relPath}`

or

path.join(absPath, relPath, relPath)

Directories vs Files

Actual files have a file extension, and never ends with no trailing slash. A directory, by comparison, is a path that does have a trailing slash for clarity

Derived Naming Rules:

dsriseah commented 4 months ago

URI versus URL versus PATHS, DIRECTORIES, and FILES

A "Uniform Resource Identifier (URI)" looks like [scheme]:[a bunch of stuff]. You use the scheme to determine how to parse the rest of it.

So URNs are used to name a resource, but it's not the only game in town:

URLs and PATHS, ETC

The closest equivalent to a path is the authority, which consists of the authority marker // that ends with the final slash. You can think of this as [user@domain] and this ends at the first / or end of line. Then comes the rest of the URL information which does look like a relPath up the last / if there is one.

The wrinkle is that while URLs are standardized, webservers are configurable to assume how to intepret the URL. A common one is to assume that if a file/resource isn't found by the strict definition of a URL, it will then assume that is a directory and look for an index to return.