DEV Community

Cover image for Feature-based: por que sua pasta components virou uma bagunça?
Matheus Silva
Matheus Silva

Posted on

Feature-based: por que sua pasta components virou uma bagunça?

Acho que todo dev já passou pelo momento de se deparar com um projeto e se perder no meio de tantos arquivos. Isso pode ser resultado de N fatores, e um deles pode ser a forma como o projeto está organizado.

Falando especificamente de frontend, quando criamos um projeto do zero em qualquer framework, ele vai lhe entregar uma estrutura padrão, chamada de Type-based em que você consegue desenvolver coisas simples, nada muito complexo ou escalável. Você vai conseguir seguir essa estrutura inicial e entregar as features necessárias, e é isso.

Até certo ponto, beleza: tudo funciona, você consegue se localizar entre as pastas e arquivos. Aí você vai integrando mais endpoints da API, adicionando features, novos fluxos, e então as coisas ficam entrelaçadas, distantes e muito desorganizadas. Implementar uma feature nova já não é tão simples, e se localizar é pior ainda.

Por que essa dor?

Isso foi uma experiência própria que vivi em projetos que desenvolvi, e que despertou minha curiosidade sobre como estruturar melhor meus projetos. Aí encontrei algumas possibilidades de arquiteturas, como DDD, Clean Architecture, MVC e Micro-frontend. Mas muitas delas eram voltadas para projetos backend, eu não via com bons olhos trazer isso para o frontend moderno e também me pareciam soluções muito complexas para algo simples.

Uma solução... Simples?

Foi aí que encontrei uma solução chamada Feature-based. É uma abordagem que parece simples, em resumo: você pega seu projeto e quebra em partes. Que partes? Bom, aí pode ser por entidade, domínio, etc. Essa quebra traz algo interessante, que é a modularidade: seu sistema agora está mais desacoplado, cada parte passa a ser autogerenciável, tem sua própria responsabilidade e seu propósito bem definido.

Dando um exemplo visual antes de seguirmos:

src/
├── features/
│   ├── movies/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── api/
│   │   └── types/
│   ├── comments/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── api/
│   │   └── types/
│   └── auth/
│       ├── components/
│       ├── hooks/
│       ├── api/
│       └── types/
├── shared/
│   ├── components/
│   ├── hooks/
│   └── utils/
└── app/
    ├── routes/
    └── layout/
Enter fullscreen mode Exit fullscreen mode

Prós e contras

Os prós? Organização: Você consegue identificar com facilidade onde trabalhar. Testabilidade: Seus fluxos de testes de e2e, integração e unitários ficam melhor localizados. E escalabilidade: Surgiu um fluxo novo? Para qual feature? Altere o código na pasta da feature que vai receber a implementação. Surgiu uma feature, entidade nova? Literalmente crie uma pasta nova em features... ou não. Acredito que aqui é um bom momento para falar dos contras.

Dando um contexto para facilitar o entendimento: imagine um cenário em que vamos adicionar os nomes das empresas produtoras na página de detalhes de um filme. Primeiro pensamento: nova entidade companies, logo vamos criar uma pasta nova de companies em features. O backend vai ter um endpoint /companies?movie_id=?, jogamos isso dentro de companies e movies vai importar o que for necessário dali. Resolvido, isso está errado? Não, é um excelente caminho e segue os requisitos para ser uma feature nova no projeto. Mas, nesse momento, é somente uma chamada para a API que retorna uma lista simples. Outra possibilidade, que também não estaria incorreta, é um simples getMovieCompanies dentro de features/movies — nesse momento é aceitável. Mas, caso companies ganhe mais fluxos e telas no projeto, aí o próximo passo é mover essa lógica para dentro de features/companies.

"Como isso se encaixa em um contra?" Aqui entra o ponto de maturidade para tomar esse tipo de decisão de implementação e levar em conta os trade-offs — nesse caso, o trabalho de criar uma nova feature versus a simplicidade do momento, em troca de uma possível refatoração no futuro. Obviamente esse exemplo é bem simples, usado só para ilustrar um cenário que poderia acontecer em um projeto real.

Conclusão

Com a IA muito presente no dia a dia de desenvolvimento, acredito que ter essa preocupação com a estrutura do projeto é importante. Sem uma estrutura bem definida, é fácil um agente duplicar lógica sem você perceber e só acabar aceitando o que foi gerado porque, aparentemente, está tudo funcionando como esperado

É isso, tem mais pontos que podem ser abordados como circular dependency, deep import, arquivos compartilhados mas isso já é um bom introdutório para pensar sobre como organizar seus projetos.
Se quiser se aprofundar mais sobre o assunto deixo aqui um pouco do que foi meu estudo sobre esse tópico contém alguns resumos e lições sobre testes, definição de features, discussões mais técnicas sobre implementação e você pode encontrar alguns exemplos de código sobre Feature-based: https://github.com/matheusdsilva01/learning/tree/main/learning-feature-based

Espero que isso tenha lhe incentivado a estruturar melhor seus projetos e tmj

Referências

https://github.com/alan2207/bulletproof-react/

Top comments (0)