Skip to content

Instantly share code, notes, and snippets.

@gabrielrochas
Created June 27, 2023 19:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabrielrochas/17838682f0730eea6e54935720b6b310 to your computer and use it in GitHub Desktop.
Save gabrielrochas/17838682f0730eea6e54935720b6b310 to your computer and use it in GitHub Desktop.
Guia Prático Para Code Review em Aplicações React com TypeScript

Guia Prático Para Code Review em Aplicações React com TypeScript

Code Smells

Componentes React que possuem muita lógica ou um número excessivo de responsabilidades podem ser difíceis de entender, testar e manter. Procure por componentes com muitos métodos, muitas linhas de código ou muitas props.

Duplicação de código é um sinal de que há oportunidades para refatorar e extrair lógica compartilhada em funções ou componentes reutilizáveis. Procure por trechos de código similares em diferentes partes da aplicação.

O acoplamento entre componentes pode dificultar a manutenção e a reutilização do código. Verifique se os componentes têm muitas dependências ou se estão acoplados a detalhes de implementação específicos.

Muitas declarações "if" ou "switch" dentro de um componente podem indicar a necessidade de separar a lógica condicional em funções ou componentes distintos. Isso pode tornar o código mais legível e mais fácil de testar.

Funções ou métodos extensos podem ser difíceis de entender e manter. Procure por funções com muitas linhas de código e tente identificar partes que possam ser extraídas em funções auxiliares mais curtas e específicas.

Um número excessivo de parâmetros em uma função pode indicar uma complexidade desnecessária. Considere refatorar o código para agrupar parâmetros relacionados em objetos ou utilizar o padrão Builder para criar objetos de configuração.

O TypeScript é uma linguagem tipada que ajuda a evitar erros e melhorar a manutenibilidade do código. Verifique se os tipos estão sendo utilizados corretamente e se há informações de tipo adequadas para evitar erros durante a execução.

Nomes de variáveis, funções ou componentes devem ser descritivos e seguir convenções estabelecidas. Procure por nomes genéricos, ambíguos ou que não descrevam adequadamente a finalidade da entidade.

Procure por código morto ou não utilizado, como variáveis, funções ou componentes que não são mais utilizados. Esses trechos de código podem ser removidos para melhorar a clareza e a manutenibilidade do código.

Componentes ou funções com várias responsabilidades diferentes podem indicar uma baixa coesão. Idealmente, cada componente ou função deve ter uma única responsabilidade claramente definida.


Exemplos de erros e soluções

1. Componentes excessivamente complexos:

  • Verifique se os componentes têm muitos métodos ou linhas de código.
  • Considere extrair lógica complexa em funções auxiliares ou componentes reutilizáveis.

Exemplo do problema:

// Componente complexo
export function ComplexComponent({ data }: Props) {
  // Muita lógica e manipulação de dados aqui...
  // Mais lógica e manipulação de dados aqui...

  return (
    // JSX renderizado usando a lógica processada...
  );
}

Exemplo da solução:

// Componente com lógica extraída
export function ComplexComponent({ data }: Props) {
  const processedData = processData(data);

  return (
    // JSX renderizado usando a lógica processada...
  );
}

function processData(data: DataType): ProcessedDataType {
  // Lógica extraída e processamento de dados...
}

voltar ao topo ⬆️

2. Lógica repetida ou duplicada:

  • Procure por trechos de código similares em diferentes partes da aplicação.
  • Identifique oportunidades para extrair lógica compartilhada em funções utilitárias ou componentes reutlizáveis.

Exemplo do problema:

// Duplicação de código
export function ComponentA() {
  // ...
  function handleClick() {
    // Código duplicado aqui...
  }
  // ...
}

Exemplo da solução:

// Lógica compartilhada extraída em função utilitária
export function ComponentA() {
  // ...
  function handleClick() {
    sharedLogic();
  }
  // ...
}

function sharedLogic(): void {
  // Lógica compartilhada...
}

voltar ao topo ⬆️

3. Acoplamento excessivo:

  • Verifique se os componentes estão fortemente acoplados a detalhes de implementação específicos.
  • Considere separar a lógica de negócio em componentes independentes e utilizar padrões de design, comoo padrão "Container/Presenter" ou "Render Props", para reduzir o acoplamento.

Exemplo do problema:

// Acoplamento excessivo
export function ParentComponent() {
  // ...
  function handleClick() {
    // Código que depende diretamente de detalhes de implementação de ChildComponent
  }
  // ...
}

Exemplo da solução (utilizando o padrão Container/Presenter):

// Componente pai (Container)
export function ParentComponent() {
  // ...
  function handleClick() {
    // Lógica do componente pai...
  }

  return <ChildComponent onClick={handleClick} />;
}

// Componente filho (Presenter)
interface ChildComponentProps {
  onClick: () => void;
}

export function ChildComponent({ onClick }: ChildComponentProps) {
  // JSX renderizado...
}

voltar ao topo ⬆️

4. Lógica condicional excessiva:

  • Procure por muitas declarações "if" ou "switch" dentro de um componente.
  • Extraia a lógica condicional em funções separadas ou componentes especializados para melhorar a legiilidade e a testabilidade.

Exemplo do problema:

// Lógica condicional excessiva
export function ComplexComponent({ data }: Props) {
  // ...
  if (condition1) {
    // ...
  } else if (condition2) {
    // ...
  } else {
    // ...
  }
  // ...

  return (
    // JSX renderizado usando a lógica condicional extraída...
  );
}

Exemplo da solução:

// Lógica condicional extraída em função separada
export function ComplexComponent({ data }: Props) {
  const renderedContent = renderContent(data);

  return (
    // JSX renderizado usando a lógica condicional extraída...
  );
}

function renderContent(data: DataType) {
  if (condition1) {
    // ...
  } else if (condition2) {
    // ...
  } else {
    // ...
  }
}

voltar ao topo ⬆️

5. Funções ou métodos muito longos:

  • Procure por funções com muitas linhas de código.
  • Identifique partes da função que possam ser extraídas em funções auxiliares ou componentes reutlizáveis.

Exemplo do problema:

// Função muito longa
export function handleComplexOperation(data: DataType): void {
  // Muitas linhas de código aqui...
}

Exemplo da solução:

// Função com lógica extraída em função auxiliar
export function handleComplexOperation(data: DataType): void {
  performPartA(data);
  performPartB(data);
  // ...
}

function performPartA(data: DataType): void {
  // Lógica extraída da função principal...
}

function performPartB(data: DataType): void {
  // Lógica extraída da função principal...
}

voltar ao topo ⬆️

6. Muitos parâmetros de função:

  • Verifique se há um número excessivo de parâmetros em uma função.
  • Considere agrupar parâmetros relacionados em objetos ou utilizar o padrão Builder para criar objeos de configuração.

Exemplo do problema:

// Muitos parâmetros
export function processUser(
  name: string,
  age: number,
  email: string,
  address: string
): void {
  // ...
}

Exemplo da solução (utilizando objeto de configuração):

// Parâmetros agrupados em objeto de configuração
interface UserConfig {
  name: string;
  age: number;
  email: string;
  address: string;
}

export function processUser(config: UserConfig): void {
  // ...
}

voltar ao topo ⬆️

7. Falta de tipagem adequada:

  • Verifique se os tipos estão sendo utilizados corretamente e se há informações de tipo adequadas para evitar erros durante a execução.
  • Utilize os recursos de tipagem do TypeScript, como tipos de propriedades e interfaces, para melhrar a legibilidade e a segurança do código.

Exemplo do problema:

// Falta de tipagem adequada
export function Component() {
  const handleClick = (event: any) => {
    // ...
  };
  // ...
}

Exemplo da solução:

// Tipagem adequada para o evento
export function Component() {
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>): void => {
    // ...
  };
  // ...
}

voltar ao topo ⬆️

8. Nomenclatura inadequada:

  • Verifique se os nomes de variáveis, funções e componentes são descritivos e seguem convenções estabelecidas.
  • Utilze nomes claros e concisos para facilitar a compreensão do código.

Exemplo do problema:

// Nomenclatura inadequada
export function Example() {
  const a = 10;

  const calculate = (n: number) => {
    // ...
  };
  // ...
}

Exemplo da solução:

// Nomenclatura adequada
export function Example() {
  const initialValue = 10;

  const calculateValue = (value: number) => {
    // ...
  };
  // ...
}

voltar ao topo ⬆️

9. Código não utilizado:

  • Procure por código morto ou não utilizado, como variáveis, funções ou componentes que não são mais utilizados.
  • Remoa esses trechos de código para manter o código limpo e evitar confusão.

Exemplo do problema:

// Código não utilizado
export function Component() {
  const unusedVariable = 'unused';

  function unusedFunction() {
    // ...
  }
  // ...
}

Exemplo da solução:

// Código não utilizado removido
export function Component() {
  // ...
}

voltar ao topo ⬆️

10. Baixa coesão:

  • Identifique componentes ou funções com várias responsabilidades diferentes.
  • Refatore o código para que cada componente ou função tenha uma única responsabilidade claramente defiida.

Exemplo do problema:

// Baixa coesão
export function handleComplexOperation(data: DataType): void {
  // ...
  // Muitas responsabilidades aqui...
  // ...
}

Exemplo da solução:

// Alta coesão com responsabilidades separadas
export function performPartA(data: DataType): void {
  // Responsabilidade A...
}

export function performPartB(data: DataType): void {
  // Responsabilidade B...
}

export function handleComplexOperation(data: DataType): void {
  performPartA(data);
  performPartB(data);
}

voltar ao topo ⬆️

@brenoangelo
Copy link

Nice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment