Skip to content

Style Guide

N Vijay Narayanan edited this page Jul 22, 2022 · 3 revisions

Coding Conventions

Coding conventions should be strictly adhered to

  1. Use PascalCase for naming of functional components and camelCase for naming of variables

    • Bad Example ❌
      const projectsList = () = {
          const variable_name = ...
      }
      
    • Good Example ✔️
      const ProjectsList = () = {
          const variableName = ...
      }
      
  2. Use UPPER_CASE naming for constants and enums

    • Bad Example ❌
    const navbarHeight = 64;
    
    • Good Example ✔️
    const NAVBAR_HEIGHT = 64;
    
  3. Avoid magic numbers, define them as constants instead

    • Bad Example ❌
    <div style={{height: calc('100%' - 64px)}}>...</div>
    
    • Good Example ✔️
    ...
    const NAVBAR_HEIGHT = 64;
    const NAVBAR_HEIGHT_REM = `${NAVBAR_HEIGHT / 16}rem`;
    const FULL_HEIGHT_MINUS_NAV = `calc(100vh - ${NAVBAR_HEIGHT_REM})`;
    ...
    <div style={{height: FULL_HEIGHT_MINUS_NAV}}>...</div>
    ...
    
    
  4. Always destructure all props (unless the entire props object needs to be passed to a child component)

    • Bad Example ❌
      const AddCohortModal: FC<Props> = (props) = {...}
      
    • Good Example ✔️
      const AddCohortModal: FC<Props> = ({ open, setOpen, mutate }) = {...}
      
  5. Use const to define components instead of function

    • Bad Example ❌
      export default function StaffCard() {...}
      
    • Good Example ✔️
      const StaffCard = () = {...}
      export default StaffCard
      
  6. Every component MUST be named

    • Bad Example ❌
      export default () => {...}
      
    • Good Example ✔️
      const HeroSignIn = () = {...}
      

Coding Best Practices

Coding best practices are guidelines to help upkeep code quality

  1. Make use of guard clauses to short circuit functions on error

    • Bad Example ❌
    if (!error) {
        ...
    } else {
        console.error(error);
        return;
    } 
    
    • Good Example ✔️
    if (error) {
        return console.error(error);
    }
    
  2. All function parameters should have well-defined types (NOT any, Object, etc)

    • Bad Example ❌
      // oldQuestion, setQuestion and atrribute have implicit `any` type
      const generateHandleTextFieldChange = (
          oldQuestion,
          setQuestion,
          attribute
      ) => {...}
      
    • Good Example ✔️
      const generateHandleTextFieldChange = (
          oldQuestion: LeanQuestion,
          setQuestion: (question: LeanQuestion) => void,
          attribute: keyof Pick<LeanQuestion, "question" | "desc">
      ) => {...}
      
  3. Avoid deep nesting (>3 levels of indentation)

  4. Avoid complicated expressions, even if it means writing more lines of code

    • Bad Example ❌
    return selectedRole === (ROLES.STUDENTS && user.student && user.student.id) || (selectedRole === ROLES.ADVISERS &&
    user.adviser &&
    user.adviser.id) || (selectedRole === ROLES.MENTORS && user.mentor && user.mentor.id) || (selectedRole === ROLES.ADMINISTRATORS &&
    user.administrator &&
    user.administrator.id)
    
    • Good Example ✔️
        if (selectedRole === ROLES.STUDENTS && user.student && user.student.id) {
        // valid student
        return true;
      } else if (
        selectedRole === ROLES.ADVISERS &&
        user.adviser &&
        user.adviser.id
      ) {
        // valid adviser
        return true;
      } else if (selectedRole === ROLES.MENTORS && user.mentor && user.mentor.id) {
        // valid mentor
        return true;
      } else if (
        selectedRole === ROLES.ADMINISTRATORS &&
        user.administrator &&
        user.administrator.id
      ) {
      // valid administrator
        return true;
      }
    
  5. Abstract logic into helper functions wherever possible, be it for improved reusability or readability

    • Bad Example ❌
      if (selectedRole === ROLES.STUDENTS && user.student && user.student.id) {
        // valid student
        return true;
      } else if (
        selectedRole === ROLES.ADVISERS &&
        user.adviser &&
        user.adviser.id
      ) {
        // valid adviser
        return true;
      } else if (selectedRole === ROLES.MENTORS && user.mentor && user.mentor.id) {
        // valid mentor
        return true;
      } else if (
        selectedRole === ROLES.ADMINISTRATORS &&
        user.administrator &&
        user.administrator.id
      ) {
      // valid administrator
        return true;
      }
    
    • Good Example ✔️
    const isValidStudent = (user: User) => {
        return user.student && user.student.id
    }
    const isValidAdviser = (user: User) => {
        return user.adviser && user.adviser.id
    }
    const isValidMentor = (user: User) => {
        return user.mentor && user.mentor.id
    }
    const isValidAdministrator = (user: User) => {
        return user.administrator && user.administrator.id
    }
    
    if (selectedRole === ROLES.STUDENTS) {
        return isValidStudent(user);
    } else if (
        selectedRole === ROLES.ADVISERS) {
        return isValidAdviser(user);
    } else if (selectedRole === ROLES.MENTORS) {
        return isValidMentor(user);
    } else if (selectedRole === ROLES.ADMINISTRATORS) {
        return isValidAdministrator(user);
    }
    
    
  6. Use switch-case statements instead of if-else blocks if it can help to improve readability

    • Bad Example ❌
    if (selectedRole === ROLES.STUDENTS) {
        return isValidStudent(user);
    } else if (selectedRole === ROLES.ADVISERS) {
        return isValidAdviser(user);
    } else if (selectedRole === ROLES.MENTORS) {
        return isValidMentor(user);
    } else if (selectedRole === ROLES.ADMINISTRATORS) {
        return isValidAdministrator(user);
    }
    
    • Good Example ✔️
    switch (selectedRole) {
        case ROLE.STUDENT:
            return isValidStudent(user);
        case ROLE.ADVISER:
            return isValidAdviser(user);
        case ROLE.MENTOR:
            return isValidMentor(user);
        case ROLE.ADMINISTRATOR:
            return isValidAdministrator(user);
        default:
            return false;
    }