Descentralize o banco de dados de suas aplicações

Vivemos um novo momento no desenvolvimento de software onde a abstração do relacionamento da aplicação com o banco de dados tende a ser cada vez maior, hoje o banco de dados não é mais o centro da aplicação.

Este é um assunto muito polêmico e que interessa tanto aos desenvolvedores de software como aos especialistas em banco de dados (DBA’s e etc).

Banco de Dados - ORM - Entidades

Quem desenvolve software a mais de 5 anos pôde acompanhar uma nova tendência crescendo rapidamente, que é a forma na qual a aplicação se relaciona com o banco de dados. Infelizmente ainda hoje os profissionais aprendem na faculdade ou no ambiente de trabalho um modelo de desenvolvimento que já está no passado, e é esta minha motivação em escrever este artigo.

Há muitos anos nosso processo de desenvolvimento vem ocorrendo de uma maneira clássica (e hoje em dia inadequada), o DBA desenvolve toda a modelagem do banco de dados elencando as entidades (tabelas) e seus relacionamentos conforme a necessidade e seu próprio entendimento do negócio, após isso aplicam-se as regras de normalização, valida-se o MER (modelo-entidade-relacional) e pronto! Basta escrever as Stored Procedures, Triggers e Views com as regras de negócio e entregar para o desenvolvedor desenvolver a aplicação que vai consumir o banco.

Então a aplicação é uma camada “casca” que envolve o banco de dados, consumindo e inserindo novas informações?

Isso parece meio ridículo para um desenvolvedor de software hoje em dia, mas esse modelo “3 camadas” já foi muito (e ainda é) pregado e defendido por ai. A primeira camada é a UI (user interface) a segunda é o “core” da aplicação que consome diretamente o banco de dados e a terceira é o próprio banco.

Um dos pontos muito defendidos nessa distribuição de 3 camadas era que a máquina do usuário não precisava possuir muito recurso computacional e nem conhecer as regras de negócio uma vez que poderia haver uma engenharia reversa da aplicação instalada.
Esse argumento não é mais válido hoje em dia dado a infinidade de recursos computacionais e tecnológicos que possuímos (Web, SOA, etc.).

Um outro forte argumento para a centralização no banco de dados é de que o servidor de banco de dados é uma máquina muito rica em recursos computacionais e consegue processar as regras de negócio com mais velocidade do que um servidor de aplicação.
Esse argumento além de passado ocasiona diversos problemas que serão abordados a seguir.

Regras de negócio em Stored Procedures é uma má prática

Poderia elencar diversos adjetivos para a utilização de regras de negócios em stored procedures, porém vamos considerar apenas uma má prática que deve ser evitada a todo custo. Listarei alguns problemas/dificuldades muito frequentes com a adoção desta prática:

  • A linguagem TSQL (Transact SQL) é muito limitada em comparação as linguagens atuais, requer mais código e dificulta a interpretação/entendimento, requer mais esforço aumentando o tempo de codificação.
  • É muito difícil escrever testes de unidade para regras de negócio em stored procedures.
  • O mecanismo que gera o plano de execução para as stored procedures não trabalha bem com condições (IF, Case, etc) podendo ocasionar uma lentidão muito grande ao chamar uma stored procedure com diversos fluxos.
  • Quebra o conceito de responsabilidade única, a regra pode estar parte no banco, parte na stored procedure. Além de aumentar o esforço na analise e detecção de problemas.
  • Estimula a escrita de milhares de linhas de código em apenas uma store procedure, algumas delas com mais de 4.000 linhas são bem fáceis de se encontrar por ai. O esforço de manutenção é centenas de vezes maior, além do risco de introdução de novos bugs.

Existem diversos contras além dos listados, porém estes citados são base de muitos problemas comuns no dia a dia. Não entenda que as stored procedures não devem ser utilizadas, até devem dependendo do cenário, porém sem regras de negócio.

E sobre o uso das Triggers?

Dentre um determinado conjunto de decisões que podem ocasionar sérios problemas entre aplicação e banco de dados, uma delas é o uso de Triggers.

Triggers podem ser úteis em alguns cenários, porém existem outras opções mais eficazes. Não há nada que uma trigger faça que não possa ser substituído por outro recurso (externo do controle do banco de dados) e que funcione de forma mais controlada, elegante, e lógico, testável.

O servidor de banco de dados é muito mais rápido que o servidor de aplicação

Fato! E deve ser mesmo, pois a questão é, quantos bancos de dados é possível escalar lado a lado? Manter bancos de dados sincronizados não é uma tarefa simples e não custa nada barato. Na maioria das aplicações existe um único banco de dados ativo (outros de contingência) e N servidores de aplicação consumindo o mesmo banco. É muito mais fácil escalar o servidor de aplicação e muito mais barato (basta conferir os valores de licenciamento de um SGBD). A própria aplicação de atualizações nos servidores de aplicação é muito mais simples do que no servidor de banco de dados.

Não é por que o banco de dados tem capacidade computacional superior que ele deve ser responsável pelo negócio em si, o banco de dados é um repositório de dados, ele deve ter alta disponibilidade para entregar com a maior velocidade possível as consultas. Utilizar os recursos computacionais do banco de dados para validar o negócio é queimar dinheiro e ocasionar problemas de performance.

O mundo é muito maior que o relacionamento entre tabelas no banco de dados

Podemos dizer que hoje o modelo de programação orientada a objetos dominou o mercado de software, sim existem ainda outros modelos (procedural, funcional, etc) porém a grande parte do mercado aderiu a famosa OOP.

Programar orientado a objetos é uma forma muito mais rica de mapear o mundo real do que as simples formas de relacionamento presentes de banco de dados relacionais, existem bancos de dados NoSQL, orientados a objetos, baseados em grafos e etc, porém não são populares como os relacionais (MSSQL, Oracle, MySQL, etc).

Se a orientação a objetos é uma forma de mapeamento mais rica que o modelo entidade-relacionamento dos bancos de dados, deveríamos então modelar nossa aplicação baseadas em classes e não em tabelas? Exato!

Partindo desta decisão como ficaria o relacionamento de uma aplicação orientada a objetos consumindo um banco de dados relacional?
Alguém já resolveu esse problema faz muitos anos, são os famosos ORM’s

O ORM (Object-relational mapping) faz justamente este trabalho, mapeando entidades de software (classes) para entidades de bancos de dados (tabelas). Com isto é possível que uma única tabela de banco de dados seja representada por N classes e vice-versa.

Os ORM’s abstraem o banco de dados

Abstrair o banco de dados significa parar de se preocupar com a modelagem do banco na hora de modelar o sistema, a modelagem pode ser feita em UML utilizando diagramas de classes entre outros diversos tipos de diagramas, no final o mapeamento das suas entidades de software estarão muito melhores definidas do que se tivessem sido feitas com base no MER de banco de dados relacionais.

O ORM cuida para que o seu mapeamento orientado a objetos faça sentido com o mapeamento entidade relacionamento.

A abstração não para por ai, através dos ORM’s é possível desligar a dependência tecnológica do banco de dados na aplicação, a aplicação não estará mais acoplada a uma tecnologia de banco de dados, trocar um banco de dados de uma aplicação não é nada trivial, porém se abstrairmos/desacoplarmos a aplicação do banco através do uso de um ORM essa tarefa seria infinitamente mais fácil.

Produtividade! Desenvolvedores não precisam codificar todas as consultas em linguagem TSQL, o ORM promove um novo modelo de consumo do banco de dados, o ORM fica encarregado de gerar as queries para comunicar-se com o banco, quando necessário o desenvolvedor pode fornecer uma query específica para ser utilizada no banco através do ORM.

Escreva sua aplicação e ganhe banco de dados

O modelo Code First já está presente faz alguns anos no mercado e seu uso vem crescendo de forma gigantesca, uma vez que possuímos o ORM para abstrair o banco de dados, por que não deixar com ele também a criação e atualização do banco?

Isso mesmo, basta mapear todo seu universo do negócio em classes, escrevê-las e no final gerar o banco de dados que se adeque a modelagem da aplicação. Afinal o banco de dados é um repositório de dados.

O Entity Framework em sua nova versão (7) trabalhará apenas com o modelo Code First, para desenvolvimento de aplicações com base de dados já existentes será possível utilizar os recursos de engenharia reversa. A atualização do banco pode ser feita também através de recursos como Migrations.

E o DBA? Morreu?

Muito pelo contrário! Quem vai garantir o perfeito funcionamento do banco? Backup, segurança, implementações de recursos de performance, acompanhar problemas em tempo real e prover rápidas soluções, dividir tabelas especiais em discos independentes e etc… Isso tudo é trabalho do DBA.

Uma coisa que está errada faz muito tempo é que a modelagem de banco de dados é de responsabilidade do DBA, criar mais um campo na tabela, escrever uma stored procedure e outras atividades desse tipo eram de decisão do DBA. Quantas vezes um desenvolvedor já precisou explicar para o DBA o por que precisava de um campo a mais numa tabela, ou por que uma stored procedure devia ser alterada. Isso não faz sentido.

Em um time de desenvolvimento o número de DBA’s é muito menor do que o número de desenvolvedores, nesse cenário o DBA iria trabalhar apenas para atender as necessidades dos desenvolvedores, deixar estas responsabilidades com o DBA é impedir de que ele faça seu real trabalho que é manter o banco de dados altamente disponível utilizando todo seu potencial.

Alguns DBA’s são contra o uso de ORM’s por que ferem seu sentimento de responsabilidade por algo que não deveria ser de sua responsabilidade. Os ORM’s aos poucos estão dando de volta aos desenvolvedores o que era para ser seu desde sempre, o domínio da modelagem e desenvolvimento da aplicação. E claro, numa situação de dúvida não custa nada perguntar a opinião do DBA.

Não importa onde estão os dados

Hoje os bancos de dados relacionais não são a única fonte de dados, os dados podem estar disponíveis através do consumo de serviços (SOA, WCF, WebAPI), podem estar em bancos NoSQL (MongoDB, Redis, etc), podem estar em bancos de dados In-Memory (Hekaton, MemSQL) ou simplesmente sendo abstraídos pelo seu ORM.

Por exemplo no DDD (Domain-Driven-Design) temos uma abstração tão grande que realmente não importa de onde vem os dados, a aplicação não fica dependente disto (apenas na camada de configuração de dados). É neste sentido que devemos caminhar, escrever aplicações focadas no domínio do negócio, que por si próprias saibam resolver qualquer problema e que possam ser expostas através de serviços para que sejam consumidas através de qualquer plataforma, device e etc…

Hoje todo gestor de desenvolvimento fala e se interessa por métodos ágeis, não existe agilidade sem teste, testes de unidade e testes de integração, abstrair o banco de dados é uma forma de promover a possibilidade dos testes, da análise do código escrito, da validação da regra de negócio, poder realizar um Mock de um repositório sem bater no banco de dados e etc. Num mundo onde dependemos de um banco de dados presente para realizar um teste de unidade, com certeza esse não é um mundo muito ágil.

Os banco de dados relacionais irão tornar-se obsoletos no futuro?

Essa mesma pergunta foi feita quando surgiram os bancos de dados orientados a objetos, bancos de dados de grafos, NoSQL.

Os bancos de dados relacionais estão acompanhando a evolução tecnológica, tornando-se cada vez mais performáticos, com mais recursos para alta disponibilidade e etc, porém de outro lado estão surgindo conceitos como Big Data que impulsiona a utilização de bancos NoSQL, redes sociais que utilizam muito o conceito de banco de dados de grafos, entre diversas novidades que não param de surgir.

Acredito que cada modelo de aplicação possui um tipo (ou tipos) de banco de dados que melhor atendem o cenário. O importante é saber como e quando utilizar cada um deles.

Para finalizar

O mundo muda constantemente e cada vez mais rápido, conceitos aprendidos na faculdade anos atrás ou até mesmo hoje em dia podem estar em constante desuso. Políticas antigas de empresas ou até mesmo profissionais conservadores de padrões ultrapassados são muito comuns no nosso mercado.

É importante estar antenado e preparado para quebrar paradigmas, pesquisar e aprofundar-se em melhores práticas de desenvolvimento de software, sempre prezando reusabilidade, performance, escalabilidade e com certeza qualidade garantida por testes de unidade.

Além deste artigo eu participei de um bate papo muito construtivo sobre este assunto com meus colegas do AspNetCast, assista o vídeo também.

* Assine meu canal no Youtube

Vamos continuar a troca de conhecimentos, deixe seu comentário abaixo, pode ser dúvida, elogio ou sua opinião que é sempre muito importante 😉

40 ideias sobre “Descentralize o banco de dados de suas aplicações

  1. Belo artigo Edu!!! Bem colocados os cenários com quais mais sofremos. Quebrar o paradigma é o desafio, que bom que o start foi dado.

    Abs

  2. Ontem assisti o bate papo, e uma coisa num consegui entender… Como seria o relacionamento N para N sem criar uma tabela “extra” no banco? =X
    O Vitor falou sobre isso, mas não consegui assimilar..

    • Cristopher, no mapeamento do seu ORM vc diz que ali ocorre um relacionamento de muitos para muitos e ele cria uma tabela para você, ou simplesmente usa uma tabela existente. Essa tabela é apenas de apoio (2 colunas Id[x] e Id[y]).

      Abs!

  3. Concordo com este artigo, 100% e na verdade sou um dos pregadores aqui na empresa que a coisa vem mudando, centralizando cada vez mais em objetos e o banco de dados apenas como mero repositor.

    Entretanto, é dificil argumentar quanto a performance!

    Nada é mais rápido quanto uma boa procedure de banco de dados e, infelizmente, não tenho conseguido bater este argumento! Não sei se estamos montando arquitetura incorreta no Entity, mas enfim, operações que envolvem dezenas ou centenas de milhares de registros, são infinitamente mais rápidas quando realizadas por uma procedure de banco.

    • Leonardo, obrigado pelo feedback!

      Vc pode fornecer a procedure para o ORM consumir, desde que seja de consulta, sem regras de negócio, tudo bem até ai!
      É necessário realizar uma configuração de tunning no EF para obter mais performance, isso é fato!

      Abs!

      • Inverte ai, considere agora dezenas de milhares de usuários fazendo processamento ao mesmo tempo neste banco de dados (executando regras de negócio nele). Não seria mais performático fazer isto na aplicação e clusterizar (ou colocar na nuvem) este processamento?
        Acredito que antes de concluir, temos que comparar os resultados em testes projetados de forma correta.

  4. Excelente o artigo. O que mais vejo no mercado são técnicas antigas, para piorar, profissionais experientes, mas desatualizados que nunca ouviram falar em ORM ou DDD e insistem em colocar tudo no BD. Além de serem irredutíveis a aceitar que as coisas têm que mudar.

  5. Parabéns Eduardo! Muito bom o artigo.
    Colaborou muito para a criação de argumentos referente a esse assunto.

    Realmente é muito difícil encontrar profissionais dispostos a evoluir juntamente com o mercado, quebrando paradigmas e se preocupando com a qualidade de seu trabalho.

    Abraço.

  6. Parabéns pelo conteúdo e a dedicação ao blog. Comecei a trabalhar com ASP.NET há pouco e seu blog tem sido a principal fonte de informações para me manter atualizado. Não vejo a hora de pegar um projeto novo e poder desenvolve-lo utilizando os modelos de arquitetura e as tecnologias que tenho visto em seus tutoriais.
    Parabéns mesmo e continue com esse vejo trabalho.

  7. Eduardo, parabéns pelo artigo. Confesso que sou um pouco das antigas, ainda tenho aplicações criadas por mim aonde usei arquitetura antiga, entidades mancas, ou seja, somente com atributos, e, acredite, toda a linguagem SQL na unha, insert, update, select, delete…rs….

    Confesso que estou aprendendo muito te seguindo no Youtube e lendo seus artigos.

    Obrigado

  8. Boa.. A melhor coisa com seus artigos é que temos o caminho a ser seguido e o mais importante os argumentos para defendelos. Huhu. Mais em relação a perfomarce e arquitetura qual é melhor Dapper ou procedure?

  9. Parabéns pelo artigo! Mas isso tudo ainda é um sonho nas maiorias das empresas que conheço. Seja fábrica ou onde área de software é meio(ai a coisa fica bem feia). Tenho 8 anos de experiência e o que vejo é a tecnologia e os conceitos evoluem numa velocidade monstra, mas as empresas não.

    Abs,

    Continue com o pelo trabalho.

  10. oi,

    Primeiro parabéns pelo belo trabalho.
    Agora, no mundo atual o correto não seria você primeiro modelar o banco de dados e só depois criar as classes.
    Em termos de produtividade é melhor
    1 – criar o banco de dados e depois fazer o mapeamento via Entity Framework.
    2 – Criar a classe (code first)

    Qual a melhor opção?

    • Reginaldo, boa noite !

      Não vou dizer que está certo ou errado, mas no modelo demonstrado e o que particularmente eu utilizo é:

      Primeiro se inicia à construção do Domínio (Classes), se for pararmos para analisar mesmo antigamente iniciando-se pela criação do BD, damos início pensando nas regras de negócio para definirmos os atributos e entidades de nosso BD, mesmo estando em nosso sub-consciente estamos pensando rs…

      Então porque não começarmos pelo domínio ??

      A engenharia reversa, que no caso seria usado no seu exemplo, por muitas vezes geram algumas classe inutilizáveis, passiveis de ajustes que você gastou seu tempo criando e não será usada.

      Aquela famosa terceira tabela de relacionamento, não seria uma classe utilizada.

      É muito mais produtivo, assertivo começar pelo Domínio, pois é aonde está toda a complexidade, concluindo isso é só finalizar utilizando um ORM (Object-relational mapping).
      Hoje temos alguns ORM’s que nos facilitam muito no mapeamento dos objetos relacionais,

      Facilidades:
      Efetuar simulações de testes (Unitário, Comportamental e etc…)
      Temos as regras de negócio toda na aplicação.. (Procedures de 2.000 linhas FORAA) rs

      Realmente acho muito mais prático, acho que temos uma barreira cultura grande sobre isso.
      Mas os estudos atuais com metodologias ágeis vão contra isso.

      Espero ter ajudado!

      Att,
      Danilo Cáceres.

  11. Parabéns pelo artigo, uma excelente síntese de argumentos para apresentar em discussões platónicas com DBAs ou integrantes da old school.

    Sempre fui defensor de evitar ao máximo uso de SP e triggers e sempre que possível migrar lógicas em stored procedures para camada de Business, Model, WhatEver mas convencer alguém está acostumado/acomodado com essa forma de trabalhar é um guerra.

  12. O assunto do seu artigo foi o tema do meu TCC em 2005. O curioso é que já se passaram 10 anos e ainda temos muitos lugares usando esse mesmo cenário. Parabéns pelo artigo, ele abre uma discussão que só tende a contribuir para que as pessoas se desconectem da matrix.

  13. Caro Eduardo,

    Eu tenho muito medo desses “Artigos” que acabam virando “Verdade Absoluta” principalmente para quem esta começando.

    Essa estratégia pode até funcionar mas em ambientes controlados e menores.

    Em ambientes Corporativos de Grandes Empresas com um volume monstruoso de dados e diversas equipes isso não deve ser incentivado por vários motivos:

    1) Administração dos Dados:

    – Imagina que em uma empresa “GIGANTE” cada desenvolvedor possa usar
    o seu CODE FIRST e cada um crie a sua “TABELINHA” ….EMPREGADO…..
    PRODUTO…GERÊNCIA, CLIENTES ETC …..

    Isso seria o CAOS. Nós teríamos milhões de dados repetidos e sem nenhuma Governança e reutilização desses dados.

    – Não podemos achar que todos os desenvolvedores sejam exímios “Modeladores de Dados”. Na maioria das vezes muitos deles não possuem se quer o conhecimento das Formas Normais.

    Será uma “BELEZA” esse relacionamento de CLASSES….

    2) Performance em Processamentos e Relatórios

    Eduardo, não sei se você experimentou processar MILHÕES de informações
    usando rotinas do C# ! É um processo muito mais lento para processar do que utilizando uma Store Procedure e todos os objetos do Banco de Dados como
    Functions, Views etc ….não tem nem como comparar…

    Poderia falar a manhã inteira aqui sobre isso mas fica a dica !

    Em TI não existe “BALA DE PRATA” e muito menos “VERDADE ABSOLUTA” !

    Grande Abraço
    Léo

      • Não vejo como uma verdade absoluta, mas como uma opção, e como já esta dito no artigo, os servidores de aplicação podem ser escalonado com maior facilidade.

        A programação orientada a objeto apresenta maior legibilidade que SQL.

        E o custo de RH hoje em dia é muito mais caro do que o custo de hardware.

        O uso de DDD pode facilitar bastante a manutenção e a organização da instituição, e talvez essa parafernaia pode ser, e quase sempre é redudancia.

        O code first não que dizer que não deva utililizar recursos já existentes.

        Na verdade você tem um modelo que atenda os requisitos apresentado para à aplicação. Que com uso de fakes ou mocks pode até rodar sem o banco de dados e por fim mapeado ao banco de dados existem ou criado apenas o que for necessário.

        Com a proposta deste artigo, você tem a oportunidade de TDD e designer patterns.

        Problemas sempre vão existir e as tecnologias vão surgindo para solucionar quando possível.

        O mundo continua.

        Não pode é parar no tempo e tentar inovar.

    • Leonardo, concordo só em pequena parte com você, onde, realmente, o ambiente corporativo demanda outra postura, mas também outra estrutura: se a coisa é grande como um ambiente corporativo, com centenas de bancos de dados, dezenas de tecnologias se miscigenando e culturas pré-OO e pós-OO convivendo sob um mesmo cenário de produção de software (eu tenho vivido esse cenário), faz-se mister que as novas tecnologias sejam abraçadas pra bem de a empresa não ‘parar no tempo’ e empregar novos funcionários com novos potenciais e as velhas tecnologias possam ser costuradas às novas, onde “se troca a turbina do avião em vôo”. Nesse cenário houve, há e sempre haverá um caldeirão de velhas e novas tecnologias, mas também deve haver gerências de infraestruturas de software e de bancos de dados, provendo essa miscigenação; frameworks; cursos de capacitação; etc…
      Realmente não existe bala de prata, tá mais pra tiroteio…

      • Leonardo, não concordo contigo.

        1. Administração de Banco de Dados
        > Não é um desenvolvedor que faz o modelo relacional, é um time de desenvolvedores apoiado pelo DBA.
        > A reutilização de dados é melhor quando o responsável é o desenvolvedor, com apoio do DBA.
        > “Relacionamento entre classes” usa o polimorfismo da OO e realmente é uma “BELEZA”.

        2) Performance em Processamentos e Relatórios
        > Na minha arquitetura, eu descentralizei o servidor de relatório do servidor de aplicações, de forma que ele pode ser replicado em um cluster ou nós da nuvem. Se tivesse feito isto no banco de dados, hoje teria um problema com isto, assim como o chará escreveu no artigo dele. Mais uma vez parabéns pelo artigo!!!

        Conclusão: Não existe realmente bala de prata e nem verdade absoluta, existe uma evolução dos processos de desenvolvimento de software. Esta evolução existe pois é necessária para aumentar a qualidade, rapidez e resolver problemas de uma melhor forma. Não fique para trás na evolução…

  14. Parabéns pela aula. E parabéns a todos que se dedicam a programação! Gosria muito q alguém me ajudasse a ter conteúdo sobre o visual studio 2015. Apostila,livro vídeo qualquer coisa se puderem me ajudar porfavor! Mande para o email: admmaues@hotmail.com
    obrigado pela atenção de todos.

  15. também tive essa resistência pois iniciei em delphi, mas aos poucos fui quebrando alguns paradigmas, e suas aulas e o seu curso é fantástico, parabéns por dividir o seu conhecimento e trazer de volta a nós desenvolvedores a responsabilidade de decidir sobre nosso modelo de dados, concordo que DBA é para fazer a manutenção e não se preocupar com tabelas e regras de negocio.

  16. Eu acho que esta havendo uma confusão nos papeis de cada profissional. O DBA é realmente a pessoa que trabalha para deixar um banco disponível e não para definir tabelas ou regras de rotinas escritas no SQL da vida. Quem faz definição do que deve ser ou não ser criado, ou mesmo se deve ou não fazer reuso, se a coluna deve ter 200 ou 2000 linhas é o AD (Administrado de Dados). Venhamos e convenhamos, deixar estrutura de bancos nas mãos dos desenvolvedores seria uma loucura. Trabalho em uma empresa com quase 200 desenvolvedores, todos os dias eu barro pelo menos 30 tabelas, umas 150 colunas e 19 funções. Eles não tem visão do que já se tem no banco, não usam (muitos nem sabem) o que é um MER (DFD), a grande maioria acha que o Hibernate resolve tudo e por ai vai. Aqui na empresa temos papeis bem definidos entre desenvolvedor, analista de sistemas, engenheiro de software, administrador de dados e DBA´s.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *