Skip to the content.

CSE 331: Coding Conventions

We will adhere to the rules described below when writing code in CSE 331. These rules should help prevent mistakes when learning JavaScript. They are not intended to represent the style used most often in industry or elsewhere.

If you write code like you've seen in class, your code should meet our code quality expectations as our code satisfies these conventions. (And if you do notice any mistakes in our code aligning with these conventions, let us know, so we can get it fixed!) If you choose to use features/methods/etc. outside of course content, make sure they follow these conventions as you could receive deductions (variable in severity), otherwise.

Types

Numbers

  • Use bigint (not number) for values that are always integers.
    • Correctness matters a lot more than performance to us.

Strings

  • Do not use charAt to access characters of strings. Use the [] notation instead (e.g. "abc"[1] is "b").
    • ([] is cleaner notation and has a more intuitive out-of-bounds result: undefined instead of "".)

Records

  • Do not access fields using obj['name'] syntax. Use obj.name instead.
    • The obj.name notation better indicates that "name" is an attribute of the "obj" record. The obj['name'] notation implies that you're trying to access an element of "obj", which is not the case. If you want to represent a collection of (key, value) pair relationships, a Map is more appropriate.
  • Do not destructure records. Always refer to records with their declared field names.

Tuples

  • Do not use tuple indexing: tuple[0]. Use a destructuring assignment to access elements with a variable name: const [a, b] = tuple;.

Declarations

  • Do not use var keyword. Use let or const instead.
  • Variables that are not intended to be changed should be declared const.

Expressions

  • Do not use == or !=. Use === and !== instead.

Conditionals

  • The condition of an if statements should evaluate to a boolean.
    • Do not use non-boolean typed variables as condition to check if they're truthy (e.g. use if(x !== undefined) instead of if(x))
    • Do not use numbers, undefined, null, NaN, etc. as conditions.
  • && should only ever be used between booleans in a conditional. Do not use && between a boolean and some operation or result to replace an if statement.

Functions

  • Do not use the function keyword. Declare a function with const f = (..) => { .. } syntax instead.
  • Anonymous functions should not be more than 1 (simple) line. If you need to use {} to contain the contents (() => { ... }), or write a 1-liner that exceeds 100 characters, create a named function instead.
  • map and filter should only be used only in simple cases. If the function you provide is more than 1 line, meaning you need to use {} to contain the contents (map(() => { ... }) or passing a reference to a named function), you should write your own loop.
  • Do not use functions that require adding new package imports (adding/changing package.json).

Classes

  • Do not declare methods with f(..) { .. } syntax. Use f = (..) => { .. } syntax instead.
  • Do not use .prototype.

Comments

  • Remove unused (including commented-out) code and lingering debugging console.logs.
  • Write explanatory inline (//) comments when they're helpful. Generally these should be brief. Below are guiding ideas for what is "helpful" though you're welcome to add more as long as they don't clutter your code.
    • Variable descriptions, if it's not obvious how it's used
      • A counter variable is likely obvious
      • A priority queue with a custom comparator that holds paths in a pathfinding algorithm is not obvious
    • State and Props descriptions in React apps
    • Complex operation descriptions. When the code isn't self documenting.
      • A comment for the line: for (const item of arr) {} that says "Iterate through every item of the array" is not helpful. The code syntax itself tells a reader the exact same thing.
    • Bug-fix history descriptions. These serve as good reminders to avoid making the same mistake twice.

More on comments to come...

Web Dev

React

  • Do not place server requests in the constructor or render. If a request is required on component start-up, use componentDidMount instead.
  • Avoid a cluttered render method.

    • Factor out distinct portions of the UI into helper methods.
    • Factor out event handlers into their own methods. Do not use inline anonymous functions except to pass arguments to a handler.
  • State update conventions:

    • Never trigger a state update from inside render. State updates trigger a rerender, which then triggers the state to update again, causing an infinite cycle.
    • Do not use consecutive setStates in a method. setState is not immediate, so this may cause bugs, and makes it less clear how a method effects the state.
    • Pass a record containing only changed states to setState.
  • Do not use React hooks. We teach the class-based components approach because it's fundamental and (believe it or not) easier to debug in many cases because state is more explicit.

  • Do not directly access and modify the DOM (using Vanilla JS methods); do it the React way.
    • Do not use window.location.reload, document.getElementById, element.innerHTML, etc.
  • Do not use bind.

Servers

  • Error responses should always be a string error message with a 40X status code. Make sure error messages are descriptive.
  • Successful responses should always be a record with a 200 (default) status code.
  • Check that every expected query and body parameter exists and is of the correct type before using it and assigning it a type.

Fetch Requests

(If you follow the fetch function structure shown in class, you will meet these requirements and your code will be well organized and readable.)

  • Every promise (fetch, json, text) you create should have a catch handler.
    • In the catch, log out a descriptive error message.
  • Check the status code of a server response before trying to access the record or error message data it contains.
  • Validate type of all data received from server before using it and assigning it a type.

Naming

Consistent, descriptive naming improves readability and removes the need for some comments because they can convey what a function/variable does immediately. We expect you to generally follow these conventions, but if your names add detail, that's likely okay.

  • Event handler and callback naming ("X" being a name/descriptor for the HTML element that fires the event and "Y" being the type of action ("click" or "change")):

    • Name props that store callbacks with the format "onY".
      • Notice this aligns with onChange or onClick as in standard HTML components.
    • Name functions that implement/handle events with the format "doXY".
  • Fetch request naming ("X" being the name of the endpoint accessed.):

    • Name functions that check the status codes of a server response "doXResp".
    • Name functions that parse the JSON data from a response "doXJson".
    • Name functions that log error messages related to fetching "doXError".

File Organization

  • Indent consistently after using 2 or 4 spaces per level.
  • Utilize white space to group related operations and separate unrelated ones.
  • If a piece of HTML has more than a couple CSS rules, factor out CSS into its own file.
  • Modularize code by separating distinct portions into separate files.