• Home

    Escolha seu Plano

    Carreiras Alura

    Evolua com profundidade técnica, direção clara e aplicação prática.

    Jornadas guiadas do básico ao avançado com checkpoints práticos, desenhadas para quem busca profundidade e protagonismo técnico.

    Iniciante

    Comece do zero com uma trilha clara e progressiva.

    Fundamentos práticos para dar os primeiros passos com segurança e construir uma base sólida.

    Intermediário

    Continue sua evolução com cursos que conectam fundamentos, ferramentas e prática profissional. Ganhe autonomia, e avance para projetos mais completos.

    Avançado

    Aprofunde temas técnicos e estratégicos para enfrentar desafios mais complexos. Explore boas práticas, arquitetura, performance com visão profissional.

    Cursos

    Ver mais cursos de Back-end
    • Pensamento computacional: fundamentos da computação e lógica de programação
    • Lógica de programação: mergulhe em programação com JavaScript
    • DDD: fundamentos do design orientado a domínio
    • ASP.NET: autenticação e autorização em APIs e aplicações web
    • Microsserviços: migração de monólitos e modularização

    Cursos

    Ver mais cursos de Dados
    • Python para Dados: primeiros passos
    • Excel: domine o editor de planilhas
    • Engenharia de Dados: Orquestração de Pipelines com Apache Airflow
    • Power BI Desktop: construindo meu primeiro dashboard
    • Governança e Arquitetura de Dados

    Cursos

    Ver mais cursos de Inteligência Artificial
    • IA: Explorando o Potencial da Inteligência Artificial Generativa
    • Engenharia de Prompt: Criando Prompts Eficazes para IA Generativa
    • Claude para Análise de Dados: prompts, integrações e automações
    • Agno: criando agentes e sistemas multiagente
    • Engenharia de software na era da IA: segurança de aplicações com agentes, MCPs e código gerado por IA

    Cursos

    Ver mais cursos de Front-end
    • HTML e CSS: ambiente, estrutura e estilo
    • React: realizando testes avançados com Jest e Testing Library
    • React: integrando TypeScript em projetos
    • JavaScript: aprendendo a programar
    • React: aplicando arquiteturas de Micro frontends

    Cursos

    Ver mais cursos de DevOps
    • Sistema Operacional Linux: fundamentos e administração prática
    • Containers e Docker: empacotamento, isolamento e gestão
    • Redes: dos conceitos iniciais à criação de uma intranet
    • Linux: gerenciando diretórios, arquivos, permissões e processos
    • Cibersegurança: Fundamentos e práticas integradas

    Cursos

    Ver mais cursos de UX & Design
    • UX Research: mapeando a experiência da pessoa usuária
    • UX/UI Design: Entregando produtos digitais com IA
    • UI Design: Prototipação e animações interativas
    • Figma: Conhecendo o programa
    • Product Design: métricas e ciclo de vida do produto

    Cursos

    Ver mais cursos de Gestão & Negócios
    • Canva: Criação de landing pages e e-mail marketing
    • Agilidade: como ela pode ajudar a criar um time de alta performance
    • Google Analytics 4: Extrair insights e configurar eventos
    • Management 3.0: gerencie o ambiente, não as pessoas
    • Automação de processos com n8n: Inteligência de dados para Marketing

    Cursos

    Ver mais cursos de Mobile
    • React Native: Estilização e Layouts com Flexbox e StyleSheet
    • Flutter: Graphql e suporte offline
    • Android com Gemini: Trabalhando com textos e imagens na IA
    • Dart: trabalhando com orientação a objetos
    • React Native: Dominando Listas com FlatList e ScrollView

    Carreiras

    Ver mais carreiras
    • Especialista em IA
    • Engenharia de IA
    • Ai native software engineering
    • Arquitetura de Soluções com IA
    • AI Product Design
    • Engenharia de Machine Learning
    • Desenvolvimento Front-End React
    • Engenharia de Dados
    • Cloud Security
    • Social Media Marketing
    • Engenharia de Agentes de IA

    Cursos

    • Engenharia de Prompt: Prompts Eficazes para IA Generativa
    • Claude Code: Criando sua Primeira Aplicação
    • Python: Crie sua Primeira Aplicação
    • Git e GitHub: Compartilhando e Colaborando
    • N8N: Fluxos de Trabalho Avançados

    Cursos

    • Copilot Studio: Solução Multiagentes
    • Padrões de API HTTP e Modelagem de APIs
    • Python para Análise de Dados com SQL
    • Docker: Criando e Gerenciando Containers
    • Design com IA: Otimizando o Processo Criativo

    Cursos

    • Model Context Protocol (MCP)
    • Spec-Driven Development: Dev Assistido por Agentes
    • Arquitetura de Sistemas Distribuídos com Java
    • Governança de Modelos e Reprodutibilidade
    • Pentest: Vulnerabilidades em Aplicações Web

    Escolha seu Plano

    Skills & Go

    O Skills & Go é para Tech Leads, Product Managers, estrategistas e early adopters que transformam ideias em soluções de alto impacto. Em cursos ao vivo e 100% online, você domina a nova era da IA em tempo real.

    Aulas ao vivo

    Saiba mais
    • Agentic Engineering: orquestre múltiplos agentes com confiabilidade
    • Building AI Products: transforme ideias em produtos reais com IA
    • AI Data Strategy: transforme dados em decisões estratégicas com IA

    Escolha seu Plano

    Eventos Alura

    Nossos eventos são pensados para quem quer estar à frente das mudanças em tecnologia, IA e inovação. Em experiências presenciais, você acompanha tendências e se conecta com especialistas que estão moldando o futuro.

    Próximos eventos

    • Imersão Engenharia de Software: Dev na Era da IA
    • IA Conference
    • Alura Signals
  • Talent Lab
  • IA

    Escolha seu Plano

    Conteúdos gratuitos

    Explore conteúdos gratuitos para aprender tecnologia no seu ritmo. Encontre artigos com conteúdos técnicos para aprender na prática, notícias para acompanhar as principais tendências do mercado e o Alura Labs, com análises e reflexões de especialistas sobre tecnologia, IA e carreira.

    Conteúdos gratuitos

    • Artigos
    • Notícias
    • Alura Labs
  • Para Empresas
Ver planos
Links principais
  • Planos e Promoções
  • Links complementares do menu mobile
  • Talent lab
  • Inteligência Artificial
  • Pós Graduações
  • Para Empresas
  • Sobre a Alura
  • Grupo Alun
  • Entrar
    • Home
    • Carreiras
    • Skills & Go
    • Talent Lab
    • Inteligência Artificial
    • Pós Graduações
    • Artigos
    • Sobre a Alura
    • Grupo Alun
    LoginContato
    • LinkedIn
    • Instagram
    • YouTube
    1. Página inicial
    2. Mobile
    3. Boas práticas do Dart para organizar um projeto

    Boas práticas do Dart para organizar um projeto

    21 min21 minutos de leitura

    21 min21 minutos de leitura

    Publicado: 15/10/2024

    1. Nomenclatura
    2. Nomeando arquivos
    3. Comentários
    4. Os princípios de SOLID
    5. Clean Code em Dart
    6. Organizando pastas
    7. Conclusão

    Assim como outras linguagens de programação, o Dart precisa seguir uma série de "normas" ou guias para a boa organização de um projeto.

    Esses guias compreendem desde convenções (ou práticas comuns) até peculiaridades que afetam diretamente no funcionamento da linguagem.

    Pois bem, é muito importante que você conheça esses guias para desenvolver o seu projeto da melhor forma possível e garantir que ele fique organizado e otimizado.

    Pensando nisso, esse artigo vai explorar as melhores dicas de boas práticas no Dart para organizar e otimizar seu projeto. Vamos lá?

    Nomenclatura

    Vamos começar com a nomenclatura. Basicamente a nomenclatura é a forma que escrevemos nomes de arquivos, nomes de classes, variáveis, entre outras convenções.

    Novamente, algumas coisas são apenas convenções e outras afetam o funcionamento do Dart.

    Banner do Guia Tático Alura sobre carreira em tecnologia, destacando o mapa da carreira tech. A imagem convida a explorar diferentes caminhos profissionais, comparar possibilidades e encontrar a próxima fase da carreira na área de tecnologia, com chamada “Explore o mapa”.

    Nomeando arquivos

    Em primeiro lugar, vamos falar sobre nome de arquivos. Escrevemos nomes de arquivos utilizando o padrão snake_case.

    O snake_case é uma forma de escrever onde todos os caracteres são minúsculos e para separar palavras utilizamos um "underscore" ou "underline", e é por conta dessa sinalização que ela se chama snake (cobra).

    Veja um exemplo:

    minha_classe.dart
    

    Nomeando variáveis

    Em variáveis utilizamos o camelCase. O nome camelCase vem da ideia de um camelo (camel) e suas corcovas.

    Começamos com a primeira palavra toda minúscula e a cada palavra nova, escrevemos apenas a primeira letra maiúscula.

    Veja um exemplo:

    String umTextoQualquer = "Aqui temos um texto qualquer";
    

    Nomeando classes

    Classes também utilizam o camelCase, mas de uma forma um pouco diferente. Ao invés de começar com a primeira letra minúscula, para diferenciar uma classe de uma variável, começamos com a primeira letra maiúscula e a cada nova palavra também.

    Esse tipo é chamado de UpperCamelCase ou PascalCase.

    Veja um exemplo:

    class ContaCorrente {
      double saldo;
      ContaCorrente(this.saldo);
    }
    void main() {
      ContaCorrente conta = ContaCorrente(1000);
    }
    

    Na definição da classe utilizamos a letra maiúscula no começo:

    class ContaCorrente
    

    Para fazer a instância também começamos com a letra maiúscula:

    ContaCorrente conta = ...
    

    Mas repare que o nome da variável começa com a letra minúscula.

    Palavras-chave e tipos

    Todas as palavras-chave do Dart são simples e minúsculas. A única exceção é a palavra Function. Você pode ver a lista completa neste link.

    Agora com tipos podemos ter algumas variações. Tipos primitivos no Dart podem ser tanto lowercase quanto UpperCamelCase.

    Exemplos de tipo lowercase:

    double
    int
    

    Exemplos de tipos UpperCamelCase:

    String
    List
    Map
    

    Espaçamentos e indentação

    Além de uma boa nomenclatura, a formatação de código também ajuda na legibilidade e organização. Precisamos identificar com facilidade onde um bloco de código começa e termina, quantos parâmetros estão sendo passados, etc.

    Vamos ver a seguir algumas formas de espaçamentos comuns no dia a dia.

    Indentação

    É como chamamos o espaçamento que inicia à esquerda do código. É a partir dele que sabemos onde um bloco de código começa e termina.

    Identificamos cada bloco de código pela distância entre ele e a margem do editor/IDE.

    Veja o exemplo a seguir:

    void main() {
      <------ Este espaçamento
      String umTexto = "Texto";
      bool temEspaco() {
        <------ Este espaçamento
        return true;
      }
    }
    

    O primeiro bloco de código não tem espaço. No nosso exemplo, a função main é iniciada sem nenhum espaço. Mas tudo que pertence ao corpo desta função, precisa de um espaçamento horizontal.

    Esse espaçamento pode variar de acordo com o projeto. Não existe uma obrigação, é apenas uma convenção.

    Por padrão, esse espaçamento é de dois espaços, ou seja, apertar duas vezes a tecla espaço. Você pode trocar esse padrão na sua IDE ou editor de código.

    Dentro da função main temos outra função temEspaco. O corpo desta última função precisa também de dois espaços.

    Mas atenção, porque ela precisa dos dois espaços da função main e depois mais dois espaços da função temEspaco, totalizando quatro espaços.

    E isso vai se repetindo enquanto for necessário.

    Uma dica para identificar se um código precisa de refatoração é observar quantos espaços estão sendo necessários para identificar blocos de código. Se muitos espaços estão sendo utilizados, talvez a função ou classe precisa ser reescrita. Cuidado, pois podem existir casos em que não há o que fazer, e está tudo bem!

    Outros espaçamentos

    É complicado categorizar todo tipo de espaçamento, mas existem outras convenções para melhorar a legibilidade de código. Veja o exemplo a seguir:

    for (var elemento in lista) {
      // fazer coisas
    }
    

    Veja os espaços entre as palavras e entre os símbolos. Novamente, é mais uma convenção e depende também do que a sua equipe ou você tem como padrão de escrita. Veja outro exemplo:

    ContaCorrente("Matheus", 10000, "333.3333.333-22");
    

    Depois de cada vírgula damos um espaço, como se fosse convenção de escrita de alguma língua como o português.

    E falando em visualização, vamos ver agora sobre comentários.

    Comentários

    Os comentários são formas de indicar e informar detalhes sobre o código que estamos escrevendo, seja como lembrete para outras pessoas desenvolvedoras ou para documentar o que cada parte do código faz e como utilizá-la.

    Devemos utilizá-los com mais frequência para manter a organização, a manutenibilidade e a facilidade de uso.

    Existem três tipos de comentários em Dart:

    • Comentário único;
    • Comentário multilinhas;
    • Comentário de documentação.

    Comentário único

    O comentário único é utilizado para pequenas anotações ou avisos. Geralmente, utilizamos para dizer que alguma feature (funcionalidade) precisa ser implementada ou arrumada, comentar o que uma linha de código faz ou, até mesmo, uma forma de dividir partes do código.

    Para escrever um comentário único, você pode utilizar duas barras (//) e depois o texto.

    Veja alguns exemplos de comentários únicos abaixo:

    // Função principal
    void main() {
      String devolveNome() {
        // TODO: fazer a função devolver um nome
        return "";
      }
      var nome = "Matheus"; // Inicializamos um nome "Matheus" à variável nome
    }
    

    Comentário multilinhas

    O comentário multilinhas tem as mesmas funções de um comentário único, exceto a de colocar comentários ao lado de códigos. Definimos um bloco de comentário utilizando a seguinte sintaxe: /* comentário */.

    Veja alguns exemplos:

    /*
    Este é um projeto exemplo.
    Para iniciar o projeto, é importante ter o Dart instalado em sua máquina.
    */
    void main() {
      String devolveNome() {
        /*
        TODO: Implementar a função.
    

    Para fazer a implementação desta função é importante receber um nome dentro da chamada da função. Depois construir uma String única que será devolvida pela função. */

    return &quot;&quot;;
    

    } }

    Comentário de documentação

    Como o próprio nome já diz, esse é o tipo de comentário utilizado para documentar o seu código. Extremamente importante se você quer construir e publicar um pacote no pub.dev.

    Sabe quando você está utilizando uma IDE como Visual Studio Code e começa a escrever um trecho de código e, de repente, aparece uma sugestão?

    Aí você não sabe se a sugestão faz o que você precisa, então você coloca o cursor por cima e lê a descrição dessa sugestão. Esse texto é gerado pelo comentário de documentação!

    Para escrever comentários de documentação, utilizamos três barras (///).

    Vamos ver um exemplo de uma função:

    void main() {
      /// Calcula a área de um círculo.
      ///
      /// @param raio O raio do círculo.
      /// @return A área do círculo.
      double calcularAreaCirculo(double raio) {
        return 3.14 * raio * raio;
      }
    }
    

    Tela do Visual Studio Code exibindo um código Dart para calcular a área de um círculo. A classe 'Area' contém um método que retorna a área do círculo. O terminal mostra o comando 'dart run' sendo executado, com a saída do valor da área de um círculo com raio 5.0 resultando em 78.5.

    O próximo tópico é uma parte muito importante para linguagens que seguem o paradigma de orientação a objetos (POO).

    Os princípios de SOLID

    É praticamente impossível falar de boas práticas no Dart sem ter um espaço falando sobre SOLID. SOLID (acrônimo) é um conjunto de princípios para linguagens que seguem o paradigma de orientação a objetos.

    Eles trazem formas de melhorar a escrita de código, tornando-o mais fácil de manter e escalar.

    S de Single Responsibility Principle

    É o princípio da responsabilidade única ou SRP. Ele diz que uma classe deve ter apenas um motivo para mudar.

    Esse princípio pode não ser imediatamente claro, mas ele indica que uma classe deve ser especializada em uma única tarefa e ter apenas uma responsabilidade dentro do projeto.

    Ou seja, evitar de escrever classes com muitas responsabilidades diferentes dentro do projeto.

    Um exemplo de responsabilidades:

    class Order {
      void calculateTotal() {}
      void addItem() {}
      void removeItem() {}
    }
    class OrderRepository {
      void save() {}
      void delete() {}
      void update() {}
      List<Order> findAll() {}
    }
    class OrderPrinter {
      void printOrder() {}
      void showOrder() {}
    }
    

    Neste exemplo, cada classe tem uma responsabilidade, respectivamente:

    • Representar um pedido e seus valores;
    • Conexão com um banco para guardar as informações de pedidos;
    • Ferramenta de visualização e pedidos.

    Sem SRP tudo ficaria dentro da mesma classe Order.

    O de Open/Closed Principle

    É o princípio Aberto-Fechado ou OCP. Objetos ou entidades devem estar abertos para extensão, mas fechados para modificação.

    Isso quer dizer que ao invés de editar a classe atual para adicionar uma nova funcionalidade, nós criamos uma nova classe que estende da classe base.

    abstract class Produto {
      String nome;
      double preco;
      Produto(this.nome, this.preco);
      double calcularFrete();
    }
    class ProdutoFisico extends Produto {
      double peso;
      double dimensao;
      ProdutoFisico(super.nome, super.preco, this.peso, this.dimensao);
      @override
      double calcularFrete() {
        return 10.0;
      }
    }
    class ProdutoDigital extends Produto {
      ProdutoDigital(super.nome, super.preco);
      @override
      double calcularFrete() {
        //Produtos digitais não possuem frete
        return 0.0;
      }
    }
    class NotaFiscal {
      double total = 0.0;
      void calculaTotal(Produto produto) {
        total = produto.preco + produto.calcularFrete();
      }
    }
    

    No código acima, nós temos declarado uma classe de produto que tem as informações básicas. Depois temos dois tipos de produtos (que herdam da classe Produto) que têm formas diferentes de calcular frete.

    Na classe de nota fiscal, independente do tipo de produto, a forma de calcular o valor total é a mesma. Se existir um novo tipo de produto com outra forma de calcular frete, basta apenas criar outra classe e depois sobrescrever o método de cálculo de frete. Desta forma não precisamos alterar nada existente no código.

    L de Liskov Substitution Principle

    É o princípio da substituição de Liskov ou LSP. Ele diz que uma classe derivada (uma classe que herda de uma classe base) deve ser substituível por sua classe base.

    A ideia é que toda classe derivada deve ter o comportamento esperado da classe base.

    Vamos pensar em uma classe funcionario que tem uma função de calcular salário. Depois, criamos uma classe que deriva de funcionario com a sua própria implementação de cálculo de salário.

    O princípio diz que independente de quantas outras classes derivadas de funcionario existirem, o comportamento de calcular salário deve ser o mesmo, ou seja, ao chamar a função, o salário daquele funcionário deve ser retornado.

    Veja a representação em código do que foi falado acima:

    abstract class Funcionario {
      double calcularSalario();
    }
    class Gerente extends Funcionario {
      @override
      double calcularSalario() {
        return 2000.0;
      }
    }
    class Vendedor extends Funcionario {
      @override
      double calcularSalario() {
        return 1000.0;
      }
    }
    class Financeiro {
      void pagarFuncionario(Funcionario funcionario) {
        print('Paga ${funcionario.calcularSalario()}');
      }
    }
    

    I de Interface Segregation Principle

    É o princípio da segregação de interface ou ISP. Ele diz que uma classe não deve ser forçada a implementar interfaces e métodos que não irão utilizar.

    Esse princípio é mais tranquilo de entender. Ao invés de ter uma interface única que possui várias funcionalidades, podemos quebrá-la em interfaces menores, assim uma classe pode implementar apenas as funcionalidades necessárias.

    Veja um exemplo em código:

    abstract class Aves {
      void botarOvo();
    }
    abstract class AvesQueVoam extends Aves {
      void voar();
    }
    class Papagaio implements AvesQueVoam {
      @override
      void voar() {
        print('Papagaio voando');
      }
    

    @override void botarOvo() { print('Papagaio botando ovo'); } } class Pinguim implements Aves { @override void botarOvo() { print("Pinguim botando ovo"); } }

    Este é um exemplo básico do princípio.

    D de Dependency Inversion Principle

    É o princípio da inversão de dependência ou DIP. Existem algumas formas de descrever esse princípio:

    • Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações;
    • Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.

    Mas e aí? O que queremos dizer com essas descrições? Basicamente queremos dizer que não devemos ter acoplamento.

    É quase impossível não existir algum nível de acoplamento em nosso código, mas devemos evitar que ele chegue num nível alto.

    Vamos pensar num sistema que faça envio de e-mails para notificação de serviços e produtos. No começo do sistema, utilizamos apenas o sistema do Gmail, mas temos planos para enviar de diversos sistemas diferentes.

    Para quem está notificando, não importa se o sistema é Gmail ou Outlook ou qualquer que seja, o que importa é que na hora de notificar por e-mail, ele seja enviado.

    Veja o exemplo em código:

    abstract class EmailSender {
      void enviarEmail(String para, String assunto, String corpo);
    }
    class GmailSender implements EmailSender {
      @override
      void enviarEmail(String para, String assunto, String corpo) {
        // Lógica para se conectar ao Gmail e enviar o email
      }
    }
    class OutlookSender implements EmailSender {
      @override
      void enviarEmail(String para, String assunto, String corpo) {
        // Lógica para se conectar ao Outlook e enviar o email
      }
    }
    class ServicoDeNotificacao {
      // Não importa se será enviado por Gmail ou Outlook, o que importa é que tenhamos a capacidade de enviar email.
      final EmailSender _emailSender;
      ServicoDeNotificacao(this._emailSender);
      void notificarPorEmail(String para, String assunto, String corpo) {
        _emailSender.enviarEmail(para, assunto, corpo);
      }
    }
    

    Para o próximo tópico vamos ver algo que está fortemente atrelado ao SOLID.

    Clean Code em Dart

    E agora mais uma técnica de escrever códigos limpos e organizados (piada proposital). Clean Code é uma "filosofia de desenvolvimento" de software e, assim como SOLID, tem os seus princípios.

    A principal ideia do Clean Code é que códigos bem escritos são mais fáceis de manter, testar e ampliar ao longo do tempo.

    Bom, quais são esses princípios?

    Nomes significativos

    É extremamente importante utilizar nomes para variáveis, funções e classes que realmente refletem o seu funcionamento e propósito.

    Para mim (e acho que para muitas outras pessoas desenvolvedoras), a parte mais difícil na hora de escrever código é nomear coisas, mas o Clean Code nos oferece algumas táticas:

    • Use nomes de variáveis que tenham significado e sejam pronunciáveis;
    • Use um vocabulário consistente para o mesmo tipo de variável;
    • Tente escrever nomes que sejam fáceis de pesquisar.

    Existem outras técnicas para nomes e se eu fosse colocar todas aqui, o artigo ficaria enorme. No final deste tópico eu vou deixar um link com uma referência para você buscar.

    Funções pequenas e com uma única responsabilidade

    É comum em algum momento do nosso desenvolvimento criarmos funções que fazem várias coisas. Nossa desculpa costuma ser "mas eu preciso fazer tudo isso para chegar no resultado esperado".

    O problema é que talvez o que está sendo executado dentro da função poderia ser quebrado em funções menores, e esse é o princípio.

    Quando as funções fazem mais que uma coisa, fica muito difícil de testar e entender seu funcionamento. Isole e simplifique.

    Comentários concisos

    Documentar o seu código deveria naturalmente fazer parte do processo de desenvolvimento, mas existe uma certa etiqueta para não criar códigos poluídos por dezenas de comentários sem sentido e desnecessários.

    • É importante comentar/documentar apenas aquilo que foi criado por você. Explique o porquê de ter feito algo. A ideia de ter nomes bem descritivos é evitar a necessidade de comentar variáveis, por exemplo. O código praticamente se autodocumenta;

    • Evite deixar trechos de código comentados. Hoje em dia todos os códigos usam algum tipo de versionamento com Git, portanto se você quer manter aquele código por algum motivo, crie uma nova branch e não deixe código comentado;

    • Não use comentários como marcador de posição. Embora a intenção possa ser manter o código bem organizado, na prática isso cria apenas poluição visual. A indentação do código já é suficiente para ajudar na organização.

    Formatação consistente

    Já foi comentado em outro tópico, mas vale reforçar: o seu código precisa ser escrito de maneira consistente.

    Nomes precisam seguir um padrão, arquivos precisam seguir um padrão e espaçamentos precisam seguir um padrão.

    Fugir da consistência dificulta a leitura e também a escrita, pois você não tem mais certeza como você deve estender o projeto.

    É como misturar inglês, português e alemão em uma mesma pergunta. Como você responde? Em espanhol?

    Testes

    Um código bem escrito é um código bem testado. Testes garantem o funcionamento da sua aplicação, tornando-a mais robusta e menos propícia a erros.

    Se você não possui testes ou uma quantidade insuficiente deles, você não tem a certeza de que tudo está funcionando de acordo.

    A aplicação pode até não quebrar, mas você não sabe se ela não quebrou porque o código está funcionando corretamente ou porque faltou pegar alguma exception no meio do caminho.

    Um processo de desenvolvimento que anda em conjunto com Clean Code é TDD (Test Driven Development) ou Desenvolvimento Orientado a Testes.

    Inclusive, se você quiser conhecer mais sobre TDD, indico esse material incrível sobre TDD em Flutter: desenvolvimento orientado a testes.

    SOLID

    E olha só! SOLID faz parte de um dos princípios de Clean Code. E não é muita surpresa já que ambos foram escritos pela mesma pessoa (Robert C. Martin. Também conhecido como Uncle Bob). Seguir os princípios de SOLID ajudam a desenvolver um código limpo e organizado.

    Como prometido, se você quiser ver mais sobre Clean Code no Dart, existe um guia criado por William Barreiro.

    Agora vamos partir para o último tópico deste artigo: organização de pastas.

    Organizando pastas

    Em um projeto Dart, temos duas pastas principais: bin e lib. Quando iniciamos um projeto Dart novo, temos um arquivo com o nome do projeto nessas duas pastas, mas o arquivo com a função main fica apenas na pasta bin.

    Então, vamos entender como funciona essa organização. Dentro da pasta bin deve ficar apenas o necessário para que o seu programa seja executado.

    Isso quer dizer apenas um arquivo com o nome do projeto e uma função main. Normalmente a função main contém poucas instruções.

    Agora tudo que compõe a aplicação precisa ficar na pasta lib. Todas as classes, interfaces, mixins, banco de dados, conexões com APIs, views, controllers e models ficam todas dentro da pasta lib.

    Veja um exemplo de organização de pastas:

    my_app/
    ├── bin/
    │   └── my_app.dart
    ├── lib/
    │   ├── models/
    │   │   ├── user.dart
    │   │   └── product.dart
    │   ├── views/
    │   │   ├── home_page.dart
    │   │   └── product_detail_page.dart
    │   ├── controllers/
    │   │   ├── user_controller.dart
    │   │   └── product_controller.dart
    │   └──  utils/
    │       ├── helpers.dart
    │       └── constants.dart
    ├── test/
    │   ├── models_test.dart
    │   └── views_test.dart
    └── pubspec.yaml
    

    A pasta test é onde você coloca todos os testes da sua aplicação. Importante separar cada parte que será testada em um arquivo diferente. Este é um caso obrigatório, pois o Dart busca testes nesta pasta.

    Existe uma pasta extra que não vem por padrão mas é utilizada como convenção: a pasta assets. Essa pasta é onde você coloca imagens, vídeos, fontes e outros arquivos textuais.

    Os arquivos na pasta assets não são compilados junto com o código Dart, eles são incluídos como recursos estáticos no aplicativo.

    Outro ponto importante é que a pasta assets deve ficar na raiz do seu projeto, junto com as pastas bin, lib e test.

    A pasta assets é comumente usada apenas no Flutter, principalmente para exibição de imagens, vídeos e tipografias dentro do aplicativo. Essa pasta é apontada através de um parâmetro no arquivo pubspec.yaml.

    Em um projeto Dart, a pasta assets não é tão utilizada. Utilizamos o pacote dart:io para leitura e escrita de arquivos e a sua localização pode variar de acordo com a necessidade. Não existe um padrão de nomenclatura ou estrutura.

    O sistema de escrita e leitura de arquivos pode ser um pouco complexo, mas você pode ler mais sobre esse assunto na documentação oficial.

    A pasta assets não funciona como um banco de dados.

    Dependências do projeto

    Agora mantendo a ideia de organização mas saindo do conceito de pastas, temos o arquivo na raiz do projeto Dart chamado pubspec.yaml.

    Neste arquivo, colocamos todas as informações relacionadas às dependências do projeto, ou seja, quais pacotes precisam ser baixados e instalados do pub.dev para fazer o projeto funcionar, quais os assets que serão utilizados, qual versão de sdk, entre outras configurações do projeto.

    Em novos projetos Dart, esse arquivo é gerado com menos informações. Veja um exemplo:

    name: nome_do_projeto
    description: A sample command-line application.
    version: 1.0.0
    # repository: https://github.com/my_org/my_repo
    environment:
      sdk: ^3.5.1
    # Add regular dependencies here.
    dependencies:
      # path: ^1.8.0
    dev_dependencies:
      lints: ^4.0.0
      test: ^1.24.0
    

    Em novos projetos Flutter, esse arquivo é gerado com mais informações. Veja um exemplo:

    name: nome_do_projeto
    description: "A new Flutter project."
    # The following line prevents the package from being accidentally published to
    # pub.dev using `flutter pub publish`. This is preferred for private packages.
    publish_to: 'none' # Remove this line if you wish to publish to pub.dev
    # The following defines the version and build number for your application.
    # A version number is three numbers separated by dots, like 1.2.43
    # followed by an optional build number separated by a +.
    # Both the version and the builder number may be overridden in flutter
    # build by specifying --build-name and --build-number, respectively.
    # In Android, build-name is used as versionName while build-number used as versionCode.
    # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
    # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
    # Read more about iOS versioning at
    # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
    # In Windows, build-name is used as the major, minor, and patch parts
    # of the product and file versions while build-number is used as the build suffix.
    version: 1.0.0+1
    
    
    environment:
    sdk: ^3.5.1
    
    
    
    Dependencies specify other packages that your package needs in order to work.
    
    
    To automatically upgrade your package dependencies to the latest versions
    
    
    consider running flutter pub upgrade --major-versions. Alternatively,
    
    
    dependencies can be manually updated by changing the version numbers below to
    
    
    the latest version available on pub.dev. To see which dependencies have newer
    
    
    versions available, run flutter pub outdated.
    
    
    
    dependencies:
    flutter:
    sdk: flutter
    
    
    
    The following adds the Cupertino Icons font to your application.
    
    
    Use with the CupertinoIcons class for iOS style icons.
    
    
    
    cupertino_icons: ^1.0.8
    
    
    
    
    dev_dependencies:
    flutter_test:
    sdk: flutter
    
    
    
    The "flutter_lints" package below contains a set of recommended lints to
    
    
    encourage good coding practices. The lint set provided by the package is
    
    
    activated in the analysis_options.yaml file located at the root of your
    
    
    package. See that file for information about deactivating specific lint
    
    
    rules and activating additional ones.
    
    
    
    flutter_lints: ^4.0.0
    
    
    
    For information on the generic Dart part of this file, see the
    
    
    following page: https://dart.dev/tools/pub/pubspec
    
    
    The following section is specific to Flutter packages.
    
    
    
    flutter:
    
    
    
    The following line ensures that the Material Icons font is
    
    
    included with your application, so that you can use the icons in
    
    
    the material Icons class.
    
    
    
    uses-material-design: true
    
    
    
    To add assets to your application, add an assets section, like this:
    
    
    assets:
    
    
    - images/a_dot_burr.jpeg
    
    
    - images/a_dot_ham.jpeg
    
    
    An image asset can refer to one or more resolution-specific "variants", see
    
    
    https://flutter.dev/to/resolution-aware-images
    
    
    For details regarding adding assets from package dependencies, see
    
    
    https://flutter.dev/to/asset-from-package
    
    
    To add custom fonts to your application, add a fonts section here,
    
    
    in this "flutter" section. Each entry in this list should have a
    
    
    "family" key with the font family name, and a "fonts" key with a
    
    
    list giving the asset and other descriptors for the font. For
    
    
    example:
    
    
    fonts:
    
    
    - family: Schyler
    
    
    fonts:
    
    
    - asset: fonts/Schyler-Regular.ttf
    
    
    - asset: fonts/Schyler-Italic.ttf
    
    
    style: italic
    
    
    - family: Trajan Pro
    
    
    fonts:
    
    
    - asset: fonts/TrajanPro.ttf
    
    
    - asset: fonts/TrajanPro_Bold.ttf
    
    
    weight: 700
    
    
    
    
    For details regarding fonts from package dependencies,
    
    
    see https://flutter.dev/to/font-from-package
    
    

    É muito interessante comparar um arquivo com o outro e ver a quantidade de instruções e informações extras que o pubspec.yaml do Flutter tem, né?

    Conclusão

    Concluir um projeto Dart bem organizado requer atenção aos detalhes e seguir boas práticas, desde a nomenclatura adequada para arquivos, variáveis ​​e classes, até a organização de pastas e a utilização correta de espaçamentos e comentários.

    Ou seja, tudo contribui para um código mais legível, manutenível e eficiente.

    Agora você já tem tudo que é necessário para começar projetos Dart e Flutter da melhor forma possível!

    Lembre-se que é importante seguir boas práticas de código estabelecidas pelo mercado, isso facilita a entrada de novas pessoas no projeto.

    Além disso, é bacana ter em mente que as informações presentes neste artigo podem servir como base para você encontrar a melhor solução para o seu projeto!

    Agora, fica o meu convite para que você aprofunde seus conhecimentos em Dart e Flutter! Vamos lá?

    Caso queira mais conteúdos sobre este tema, acesse o link:

    • Dart: trabalhando com a sintaxe e configuração de projeto

    Até a próxima!

    Banner do Guia Tático Alura sobre carreira em tecnologia, destacando o mapa da carreira tech. A imagem convida a explorar diferentes caminhos profissionais, comparar possibilidades e encontrar a próxima fase da carreira na área de tecnologia, com chamada “Explore o mapa”.

    Avalie este artigo

    • Foto de MATHEUS ALBERTO MARCUS

      Autor(a)

      MATHEUS ALBERTO MARCUS

    Explore por tópico

    • Back-end
    • Dados
    • DevOps
    • Front-end
    • Gestão & Negócios
    • Institucionais
    • Inteligência Artificial
    • Mobile
    • UX & Design

    Leia também

    • 25/09/2023

      Arquitetura Flutter: como escolher a melhor arquitetura para projetos

      Ler mais
    • 06/08/2024

      BloC ou Cubit no Flutter: qual escolher?

      Ler mais
    • 17/05/2016

      Como fazer requisição HTTP no Android com OkHttp: guia para consumir APIs

      Ler mais
    Ver mais conteúdos

    Inscreva-se em nossa Newsletter

    Fique por dentro de conteúdos, insights e oportunidades do universo tech. Receba novidades e lançamentos direto no seu e-mail.

    Institucional

    • Sobre nós
    • Trabalhe Conosco
    • Para Empresas
    • Para Escolas
    • Política de Privacidade
    • Compromisso de Integridade
    • Termos de Uso
    • Canal de Ética
    • Código de Ética
    • Fale Conosco
    • Documentos Institucionais
    • Status
    Institucional
    • Sobre nós
    • Trabalhe Conosco
    • Para Empresas
    • Para Escolas
    • Política de Privacidade
    • Compromisso de Integridade
    • Termos de Uso
    • Canal de Ética
    • Código de Ética
    • Fale Conosco
    • Documentos Institucionais
    • Status

    A Alura

    • Como Funciona
    • Inteligência Artificial
    • Plataforma
    • Depoimentos
    • Instrutores(as)
    • Dev em <T>
    • Luri, a Inteligência Artificial da Alura
    • IA Conference
    • Cursos Imersivos
    • Perguntas Frequentes
    A Alura
    • Como Funciona
    • Inteligência Artificial
    • Plataforma
    • Depoimentos
    • Instrutores(as)
    • Dev em <T>
    • Luri, a Inteligência Artificial da Alura
    • IA Conference
    • Cursos Imersivos
    • Perguntas Frequentes

    Conteúdos

    • Alura Cases
    • Imersão Engenharia de Software: Dev na Era da IA
    • Artigos
    • Podcasts
    • Artigos de educação corporativa
    Conteúdos
    • Alura Cases
    • Imersão Engenharia de Software: Dev na Era da IA
    • Artigos
    • Podcasts
    • Artigos de educação corporativa
    Uma Empresa do GrupoLogo Grupo Alun

    Outras empresas do Grupo Alun

    • FIAP
    • STARTSE
    • PM3
    • LUMINA

    Ao submeter seu e-mail, você concorda com a política de privacidade da Alura.

    Redes Sociais & Apps

    instagram
    youtube
    tiktok
    x
    appStore
    googlePlay
    Uma Empresa do GrupoLogo Grupo Alun

    Outras empresas do Grupo Alun

    • FIAP
    • STARTSE
    • PM3
    • LUMINA

    Ao submeter seu e-mail, você concorda com a política de privacidade da Alura.

    Redes Sociais & Apps

    instagram
    youtube
    tiktok
    x
    appStore
    googlePlay
    Alura