193 |
194 | São Classes do pacote java.time, utilizadas para a manipulação de Data e Hora, que oferecem Métodos para formatar, converter e realizar cálculos com datas, como por exemplo, encontrar o intervalo de tempo entre 2 datas.
195 |
196 | | Classe | Descrição |
197 | | ----------------- | ------------------------------------------------------------ |
198 | | **LocalDate** | Armazena uma data. |
199 | | **LocalTime** | Armazena um horário. |
200 | | **LocalDateTime** | Armazena uma data e um horário em um único Objeto. Esta Classe é muito utilizada para receber a data e o horário em que um Objeto foi criado ou atualizado. |
201 |
202 |
Documentação: Classes Local Date, LocalTime e LocalDateTime
203 |
204 |
205 |
206 |
207 |
Deploy do Backend no Heroku - Github Organization
2 |
3 | Quando estamos trabalhando com Organizações, além de conectar o Heroku com a Conta do Github é necessário autorizar o acesso do Heroku na Organização, para poder acessar os repositórios.
4 | Neste material, o Passo 11 foi adaptado para o Deploy do Projeto Integrador via Github Organization. Substitua o Passo 11 do Guia do Deploy do Projeto Blog Pessoal pelas instruções abaixo. Os demais passos são iguais.
5 |
6 | |

|
**ATENÇÃO:** *Crie a conta no Heroku utilizando o e-mail que foi criado para o projeto, ou seja, a mesma conta que o grupo utilizou para criar a conta no Github, onde foi criada a Organização*.
|
7 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
8 |
9 |
👣 Passo 11 - Deploy da Organização no Heroku
10 |
11 | 1. Para configurar o **Deploy** do seu projeto, clique na guia **Deploy**.
12 |
13 |
14 |
15 | 2. Na sequência, clique no ícone do **Github**
16 |
17 |
18 |
19 | 3. No item **App connected to Github**, clique no botão **Connect to Github**
20 |
21 |
22 |
23 | 4. Conecte-se com a conta do **Github do Projeto Integrador**.
24 |
25 |
26 |
27 | 5. Na próxima tela, não esqueça de liberar o acesso do Heroku na Organização, como mostra a figura abaixo, clicando no botão **Grant** ao lado da Organização (em nosso exemplo **Projeto-Integrador-Modelo**).
28 |
29 |
30 |
31 | 6. Em seguida clique no botão **Authorize heroku**
32 |
33 | 7. Caso você não tenha autorizado o Heroku no passo anterior, depois de conectar a conta do Heroku com a conta do Github, clique no link **Ensure Heroku Dashboard has team access**, conforme indicado na figura abaixo:
34 |
35 |
36 |
37 | 8. Na próxima tela, clique no botão **Grant** ao lado da Organização (em nosso exemplo **Projeto-Integrador-Modelo**), como mostra a figura abaixo, para liberar o acesso.
38 |
39 |
40 |
41 | 9. Observe que no Item **Select for a repository to connect to** estará disponível tanto a Conta do Github, quanto a Organização. Selecione a Organização, em nosso exemplo **Projeto-Integrador-Modelo**
42 |
43 |
44 |
45 | 4. Em seguida, vamos procurar o **Repositório do Projeto Integrador**
46 |
47 | 7. No item **Connect to Github**, na caixa de pesquisa **repo-name**, digite o **Nome do Repositório do Projeto Integrador, em nosso exemplo backend,** e clique no botão **Search**.
48 |
49 |
50 |
51 | 8. Será exibido o repositório. Clique no botão **Connect** ao lado do Repositório backend.
52 |
53 |
54 |
55 | 9. Observe que o Heroku indicará que a aplicação está **Conectada com o Repositório**.
56 |
57 |
58 |
59 | 10. No item **Automatic deploys**, no item **Choose a branch to deploy**, selecione a **Branch** que será usada para fazer o Deploy (main). Na sequência, clique no botão **Enable Automatic Deploys**, para automatizar o processo, ou seja, toda vez que você fizer um **push no Repositório no Github**, o Heroku tentará fazer o Deploy automaticamente.
60 |
61 |
62 |
63 |
64 | |

|
**ATENÇÃO:** *O Deploy automático será concluído, APENAS E SOMENTE SE o código que foi enviado para o Github esteja sem erros e com o perfil PROD habilitado.
|
65 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
66 |
67 |
68 | 11. No item **Manual deploy**, clique no botão **Deploy branch**.
69 |
70 |
71 |
72 | 12. Logo abaixo, será exibida a janela do **Console do Heroku**. Acompanhe o processo do Deploy e aguarde a conclusão
73 |
74 |
75 |
76 | 13. Se o Deploy foi bem sucedido, será exibida a mensagem **Deploy to Heroku - Your app was succesfully deployed**.
77 |
78 |
79 |
80 | 14. Clique no botão **View** para abrir a aplicação.
81 |
82 | |

|
**ATENÇÃO:** *Caso aconteça algum erro no processo do Deploy será exibida a mensagem: Build failed!. Verifique o seu código e tente novamente.
|
83 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/03_spring/uml.md:
--------------------------------------------------------------------------------
1 |
Diagrama de Classes
2 |
3 | A **Programação Orienteda à Objetos (POO)** é um paradigma baseado no conceito de envolver dados (**Atributos**), e comportamentos (**Métodos**), relacionados aqueles dados, em uma coleção chamada Objetos, que são construídos de um conjunto de “planos de construção” (**Métodos Construtores**), definidos por uma pessoa Desenvolvedora ou por um Analista de Sistemas, chamados de **Classes**. Uma Classe é como uma planta de construção que define a estrutura para objetos, que são instâncias concretas daquela Classe.
4 |
5 | Da mesma forma que o **DER**, Diagrama de Entidades e Relacionamentos apresentam o nosso Modelo de dados Relacional de forma gráfica, o **Diagrama de Classes** representam de forma gráfica as nossas Classes e as suas relações. A **UML** (Unified Modeling Language), que **significa** Linguagem Unificada de Modelagem, é a linguagem padrão para modelagem de sistemas que seguem o paradigma da Orientação a Objetos. A UML é utilizada na construção dos Diagramas de Classes e outros tipos de Diagramas como o Diagrama de Casos de Uso, Diagrama de Sequência e etc. Neste material vamos focar no Diagrama de Classes.
6 |
7 |

8 |
9 | Observe no Diagrama de Classe acima que podemos visualizar todos os Métodos e Atributos que compõem a Classe Cat, inclusive a visibilidade, simplificando processo de implementação.
10 |
11 |
Relações entre objetos
12 |
13 | Quando falamos de uma única Classe, tudo fica muito simples, entretanto, nenhuma aplicação Orientada a Objetos se resume em apenas uma Classe, e além disso, os Objetos gerados por estas Classes possuem relações entre si, de acordo com o planejamento do projeto. Para simplificar o entendimento destas relações, construímos os Diagramas de Classes com as suas respectivas Relações. Vamos conhecer os tipos de relação entre os Objetos:
14 |
15 |
Herança
16 |
17 | A Herança é a habilidade de construir novas Classes em cima de Classes já existentes. O maior benefício da herança é a reutilização de código. Se você quer criar uma Classe que é apenas um pouco diferente de uma já existente, não há necessidade de duplicar o código. Ao invés disso, você estende a Classe existente e coloca a funcionalidade adicional dentro de uma subClasse resultante, que herdará todos os campos de Métodos da superClasse.
18 |
19 |
20 |
21 | No exemplo acima, Gato é um animal, logo ele herda todas características da Classe Animal.
22 |
23 |
Implementação
24 |
25 | Interfaces são um conceito da programação orientada a objetos que tem a ver com o comportamento esperado para uma ou um conjunto de Classes. Interfaces definem o que uma Classe deve fazer e não como. Assim, interfaces não possuem a implementação de Métodos pois apenas declaram o conjunto de Métodos.
26 |
27 | Na interface, todos os Métodos são portanto abstratos e públicos, já que são apenas declarados na interface sendo obrigatoriamente implementados pelas Classes que implementam a interface. Uma vez definida uma interface é implementada pelas Classes de devem ter o comportamento descrito na interface, ou seja, devem ter os mesmos Métodos definidos na interface. Dizemos que as Classes implementam a interface pois de fato uma Classe ao implementar uma interface deve prover a implementação de todos os Métodos definidos na interface.
28 |
29 | Em diagramas UML, o relacionamento de Implementação é mostrado por uma seta igual a da Herança, com a linha tracejada, desenhada de um objeto e apontada para outro que ele implementa.
30 |
31 |

32 |
33 | No exemplo acima, a Classe Cat está implementando os Métodos das Interfaces Quatro Patas e Respira Oxigênio
34 |
35 |
Associação
36 |
37 | A associação é um relacionamento no qual um objeto usa ou interage com outro. Em diagramas UML, o relacionamento de
38 | associação é mostrado por uma seta simples desenhada de um objeto e apontada para outro que ele utiliza. A propósito,
39 | ter uma associação bi-direcional é uma coisa completamente normal. Neste caso, a flecha precisa apontar para ambos. A
40 | associação pode ser vista como um tipo especializado de dependência, onde um objeto sempre tem acesso aos objetos os quais ele interage, enquanto que a dependência simples não estabelece uma ligação permanente entre os objetos.
41 |
42 |
43 |
44 | No exemplo acima, Professor interage com aluno.
45 |
46 |
Agregação
47 |
48 | A agregação é um tipo especializado de associação que representa relações individuais, múltiplas, e totais entre múltiplos objetos, enquanto que uma associação simples descreve relações entre pares de objetos.
49 | Geralmente, sob agregação, um objeto “tem” um conjunto de outros objetos e serve como um contêiner ou coleção. O componente pode existir sem o contêiner e pode ser ligado através de vários contêineres ao mesmo tempo.
50 |
51 | Em Diagramas UML a relação de agregação é mostrada como uma linha e um diamante vazio na ponta do contêiner e uma flecha apontando para o componente.
52 |
53 |
54 |
55 | No exemplo acima, um objeto Departamento contém diversos professores e os objetos professores continuam existindo mesmo sem o objeto departamento.
56 |
57 |
Composição
58 |
59 | A composição é um tipo específico de agregação, onde um objeto é composto de um ou mais instâncias de outro. A distinção entre esta relação e as outras é que o componente só pode existir como parte de um contêiner. No UML a relação de composição é desenhada do mesmo modo que para a agregação, mas com um diamante preenchido na base da flecha.
60 |
61 |
62 |
63 | No exemplo acima, a universidade consiste de departamentos e os departamentos só existem enquanto o objeto universidade existir.
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/04_fluxo_git/02_github_organizations.md:
--------------------------------------------------------------------------------
1 |
Criando uma Organização no Github
2 |
3 | As organizações são contas compartilhadas onde empresas e projetos de código aberto podem colaborar em muitos projetos de uma vez. Os proprietários e administradores podem gerenciar o acesso de integrantes aos dados e projetos da organização com recursos avançados administrativos e de segurança.
4 |
5 | Com a Organização, o Administrador consegue criar vários repositórios em um único lugar e conceder acessos específicos para cada membro ou time. Como um integrante da organização, você pode visitar o painel da sua organização durante todo o dia para se manter atualizado sobre as atividades recentes e acompanhar problemas e pull requests nos quais está trabalhando ou seguindo na organização.
6 |
7 | No projeto Integrador, a Organização será composta por 3 Repositórios:
8 |
9 |
10 |
11 | Repositório |
12 | Conteúdo |
13 |
14 |
15 | Documentação |
16 | Arquivos contendo a documentação da API:
17 | - Escopo do Projeto atualizado
18 | - Documentação do Banco de Dados (DER, SQL e Dicionário de dados)
19 | - Documentação do Backend (Documentação das Classes e PDF do Swagger)
20 | - Documentação do Frontend
21 | |
22 |
23 |
24 | Backend |
25 | Projeto Spring completo |
26 |
27 |
28 | Frontend |
29 | Projeto Angular/React Completo |
30 |
31 |
32 |
33 |
Passo 01 - Preparação do ambiente
34 |
35 | 1. Crie uma conta de e-mail gratuita com o nome do projeto (Gmail).
36 |
37 | 2. Crie uma conta gratuita no Github utilizando o e-mail criado com o nome do projeto.
38 |
39 |
Passo 02 - Criando a Organização e adicionando os Membros
40 |
41 | Neste passo, vamos criar uma organização dentro da conta do Github que o Grupo criou.
42 |
43 | 1. Na Barra de Navegação superior da Conta do Github, clique no botão **+** e no menu que será aberto, clique na opção **New organization**.
44 |
45 |
46 |
47 | 2. Na próxima tela, role para baixo e clique no botão **Create a free organization**.
48 |
49 |
50 |
51 | 3. Na próxima tela, configure com os dados do seu projeto.
52 |
53 |
54 |
55 | | Item | Dados |
56 | | -------------------------------- | --------------------- |
57 | | **Organization account name** | Nome do seu projeto |
58 | | **Contact e-mail** | E-mail do seu projeto |
59 | | **This organization belongs to** | My personal account |
60 |
61 | 4. Ao final, faça a verificação de segurança da sua conta clicando no botão **Verificar** e ao finalizar clique no botão **Next**.
62 |
63 |
64 |
65 | 5. Na próxima tela, adicione todos os membros do seu grupo na Organização, através da conta do Github de cada integrante. Ao final clique no botão **Complete setup**.
66 |
67 |
68 |
69 | 6. Na próxima tela, preencha conforme a figura abaixo e clique no botão **Submit** para concluir.
70 |
71 |
72 |
73 |
74 |
75 | 7. Os integrantes do grupo irão receber um **e-mail com o convite** para fazer parte da Organização, semelhante a figura abaixo:
76 |
77 |
78 |
79 | 8. Clique no botão **Join** para aceitar o convite.
80 |
81 | 9. Após clicar no botão **Join**, o Github solicitará a senha do Github pessoal para confirmar a aceitação do convite.
82 |
83 |
Passo 03 - Criando Repositórios na Organização
84 |
85 | Neste passo vamos criar os nossos Repositórios Remotos.
86 |
87 | 1. Na tela inicial da Organização, clique no botão **Create a new repository**.
88 |
89 |
90 |
91 | 2. Na próxima tela, crie um **Repositório Público**, chamado **backend** e adicione o arquivo **Readme.MD**. Em seguida clique no botão **Create Repository**.
92 |
93 |
94 | 3. Repositório Criado
95 |
96 |
97 |
98 | 4. Crie os demais Repositórios clicando no botão **New**.
99 |
100 |
101 |
102 |
Passo 04 - Criando um Time de Desenvolvimento
103 |
104 | Time de Desenvolvimento ou Teams, são grupos de membros da organização que refletem a estrutura de sua empresa ou grupo de um Projeto, com permissões e menções de acesso em cascata aos repositórios da Organização.
105 |
106 | Os proprietários da organização e os mantenedores da equipe podem conceder às equipes acesso de administração, leitura ou gravação aos repositórios da organização. Os membros da organização podem enviar uma notificação para uma equipe inteira mencionando o nome da equipe. Os membros da organização também podem enviar uma notificação para uma equipe inteira solicitando uma revisão dessa equipe. Os membros da organização podem solicitar revisões de equipes específicas com acesso de leitura ao repositório onde a solicitação pull é aberta.
107 |
108 | Neste passo vamos criar um time de desenvolvimento.
109 |
110 | 1. Na página inicial da Organização, clique na opção **Teams** (Indicado na imagem em azul). Em seguida clique no botão **New team** (Indicado em vermelho na imagem).
111 |
112 |

113 |
114 | 2. Configure conforme a imagem abaixo e clique no botão **Create team**. Se o Grupo desejar, pode alterar o nome do Time.
115 |
116 |
117 |
118 | 3. Na página inicial do Time, em **Members**, clique no **botão +** para adicionar os integrantes do Grupo no Time.
119 |
120 |
121 |
122 | 4. Clique no botão **Add a member** para adicionar um novo membro no time.
123 |
124 |
125 |
126 | 5. Na próxima tela, localize os integrantes do grupo e clique no botão **Invite**.
127 |
128 |
129 |
130 | 6. Como os integrantes do grupo já fazem parte da Organização, todos receberão uma mensagem via e-mail informando que foram adicionados no time.
131 |
132 |
Passo 05 - Adicionando o Time no Repositório
133 |
134 | Neste passo, vamos adicionar o time nos Repositórios do Projeto.
135 |
136 | 1. Na tela inicial do Repositório (no exemplo abaixo, backend), clique no link **Settings**.
137 |
138 |
139 |
140 | 2. Na próxima tela, no menu lateral do lado esquerdo da tela, clique na opção **Collaborators & teams**.
141 |
142 |
143 |
144 | 3. Ainda nesta tela, clique no botão **Add teams**.
145 |
146 |
147 |
148 | 4. Na próxima tela, selecione o **Time** (indicado em azul na imagem abaixo) na opção **Choose role**, vamos deixar com **Administrador** (indicado em vermelho na imagem abaixo). Desta forma, todos os Integrantes do Grupo terão acesso total ao Repositório.
149 |
150 |
151 |
152 | 5. Clique no botão **Add** (botão verde), para concluir.
153 | 6. Repita estes passos nos demais repositórios do projeto.
154 |
155 | |

|
**ATENÇÃO:** Como todos os Integrantes do Grupo terão acesso de Administrador do Repositório, tenham cuidado para manter o repositório organizado e sem erros.
|
156 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
157 |
158 |
Passo 06 - Personalizando a Organização
159 |
160 | 1. Clique sobre logo da Organização
161 |
162 |
163 |
164 | 2. Na janela General, para alterar ou inserir o logo do projeto, clique no botão **Upload new picture**, na sessão **Profile picture** e selecione o novo logo.
165 |
166 |
167 |
168 | 3. Ainda nesta janela, personalize as informações da Organização como mostra a figura abaixo, ajustando os dados para o seu projeto.
169 |
170 |
171 |
172 | |

|
**ATENÇÃO:** O item **URL**, **deverá ser preenchido apenas no final do Bloco 03**, quando o Frontend estiver concluído e na nuvem.
|
173 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
174 |
175 | 4. Clique no botão **Update Profile** para concluir. O resultado você confere na imagem abaixo:
176 |
177 |
178 |
179 |
180 |
181 |
182 |
--------------------------------------------------------------------------------
/04_fluxo_git/03_deploy_organizacao_render.md:
--------------------------------------------------------------------------------
1 |
Deploy do Backend no Render - Github Organization
2 |
3 | Quando estamos trabalhando com Organizações, além de conectar o Render com a Conta do Github é necessário autorizar o acesso do Render na Organização, para poder acessar os repositórios.
4 | Neste material, o Passo 09 foi adaptado para o Deploy do Projeto Integrador via Github Organization. Substitua o Passo 09 do Guia do Deploy do Projeto Blog Pessoal pelas instruções abaixo. Os demais passos são iguais.
5 |
6 | |

|
**ATENÇÃO:** *Crie uma nova conta no Render utilizando o e-mail que foi criado para o projeto, ou seja, a mesma conta que o grupo utilizou para criar a conta no Github, onde foi criada a Organização*.
|
7 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
8 |
9 |
👣 Passo 09 - Criar o Web Service no Render a partir de uma Organização
10 |
11 | 1. Na barra de menus principal do Render, clique no item Dashboard, como mostra a imagem abaixo:
12 |
13 |
14 |
15 | 2. Para adicionar um novo Web Service, no Dashboard do Render, clique no botão **New +** e em seguida clique na opção **Web Service**.
16 |
17 |
18 |
19 | 3. No item **GitHub**, clique no link **+ Connect account**, para conectar a sua conta do Render com a sua Conta do Github.
20 |
21 |
22 |
23 | 4. Na tela, **Install Render**, clique na **Organização** que foi criada na conta do Github do Projeto Integrador (no exemplo abaixo, **Projeto-Integrador-Modelo**), como mostra a figura abaixo:
24 |
25 |
26 |
27 | 5. Na próxima tela, clique no botão **Install**, para concordar que o Render acesse a Organização no Github.
28 |
29 |
30 |
31 | 6. Conecte o Render com o Repositório onde você enviou o **Backend do Projeto Integrador**, clicando no botão **Connect**, localizado ao lado do Repositório.
32 |
33 |
34 |
35 | 7. Na próxima tela, informe o nome da sua aplicação na propriedade **Name** (nome do seu projeto integrador) e verifique se a propriedade **Environment** está com a opção **Docker** selecionada.
36 |
37 |
38 |
39 |
40 |
41 | |

|
**ATENÇÃO:** O NOME DO PROJETO NÃO PODE CONTER LETRAS MAIUSCULAS, NUMEROS OU CARACTERES ESPECIAIS.
|
42 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
43 |
44 |
45 |
46 | 8. Role a tela para baixo e verifique se o Plano Gratuito (**Free**) está selecionado.
47 |
48 |
49 |
50 |
51 |
52 | |

|
**ATENÇÃO:** *Caso seja selecionado um plano diferente, o Render exigirá o Cartão de Crédito para emitir a fatura do serviço.
|
53 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/04_fluxo_git/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
Bootcamp - Java Full Stack
5 |
6 |
Fluxo de trabalho Git
7 |
8 | 1.
Trabalhando em Equipe com o Github
9 | 2.
Guia de Configuração de uma Organização no Github - Git Organization
10 |
11 |
12 |
13 |
14 |
Home
15 |
--------------------------------------------------------------------------------
/05_devops/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
Bootcamp - Java Full Stack
5 |
6 |
DevOps
7 |
8 | 1.
Introdução ao SOLID Pattern
9 | -
Princípio da Responsabilidade Única
10 | -
Princípio Aberto-Fechado
11 | -
Princípio da Substituição de Liskov
12 | -
Princípio da Segregação de Interfaces
13 | -
Princípio da Inversão de Dependências
14 |
15 | 2.
Introdução ao Domain-Driven Design - DDD
16 | 3.
Introdução ao Test-Driven Development - TDD
17 | -
TDD na prática
18 |
19 | 4.
Introdução a Containers
20 | 5.
Introdução a Orquestradores de Containers
21 | -
Docker Swarm na prática
22 |
23 | 6.
Continuous Integration / Continuous Delivery (CI/CD)
24 | -
Introdução a Github Actions
25 | -
CI/CD na prática
26 |
27 |
28 |
29 |
30 |
31 |
Home
32 |
--------------------------------------------------------------------------------
/05_devops/github_actions.md:
--------------------------------------------------------------------------------
1 |
Introdução ao Github Actions
2 |
3 |
4 |
5 | O **Github Actions** permite que você crie fluxos de trabalho de ciclo de vida de desenvolvimento de software personalizados diretamente em seu repositório Github. Esses fluxos de trabalho são compostos de diferentes tarefas chamadas ações (actions), que podem ser executadas automaticamente em determinados eventos.
6 |
7 | Isso permite incluir recursos de integração contínua (CI) e implantação contínua (CD) e muitos outros recursos diretamente em seu repositório.
8 |
9 |
1. Conceitos básicos
10 |
11 | Vamos conhecer os principais conceitos usados no Github Actions com os quais você deve estar familiarizado ao usá-lo ou ao ler a documentação:
12 |
13 |
1.1. Actions
14 |
15 | As ações são o menor bloco de construção portátil de um fluxo de trabalho e podem ser combinadas como etapas para criar um trabalho. Você pode criar suas próprias ações ou usar ações compartilhadas publicamente no Marketplace.
16 |
17 |
1.2. Event
18 |
19 | Os eventos são atividades específicas que acionam a execução de um fluxo de trabalho. Por exemplo, um fluxo de trabalho é acionado quando alguém envia para o repositório ou quando uma solicitação pull é criada. Os eventos também podem ser configurados para ouvir eventos externos usando Webhooks.
20 |
21 |
1.3. Run
22 |
23 | Um executor é uma máquina com o aplicativo executor do Github Actions instalado. Em seguida, o executor aguarda os trabalhos disponíveis que pode executar. Depois de escolher um trabalho, eles executam as ações do trabalho e relatam o progresso e os resultados de volta ao Github. Os executores podem ser hospedados no Github ou auto-hospedados em suas próprias máquinas/servidores.
24 |
25 |
1.4. Job
26 |
27 | Uma tarefa é composta de várias etapas e é executada em uma instância do ambiente virtual. As tarefas podem ser executadas independentemente umas das outras ou sequencialmente se a tarefa atual depender da tarefa anterior para ser bem-sucedida.
28 |
29 |
1.5. Step
30 |
31 | Uma etapa é um conjunto de tarefas que podem ser executadas por um trabalho. As etapas podem executar comandos ou ações.
32 |
33 |
1.6. Workflow
34 |
35 | Um fluxo de trabalho é um processo automatizado composto por um ou vários trabalhos e pode ser acionado por um evento. Os fluxos de trabalho são definidos usando um arquivo YAML no diretório .github/workflows. Na prática, o Workflow é um Pipeline CI/CD.
36 |
37 |
2. Github Marketplace
38 |
39 | A maneira mais fácil de iniciar seu fluxo de trabalho é usando um dos muitos modelos de fluxo de trabalho e ação disponíveis no Github Marketplace. Se você não tiver certeza de quais ações podem ser úteis, dê uma olhada nas sugestões fornecidas pelo Github, que são exclusivas para cada repositório.
40 |
41 |
42 |
43 |
Github Marketplace
44 |
45 |
46 |
47 | Neste repositório existem modelos de actions para diversas tarefas de um pipeline CI/CD, como executar o Java, fazer o Deploy no Azure, entre outras.
48 |
49 |
3. A Linguagem YAML
50 |
51 | **YAML** é uma linguagem de serialização legível por humanos orientada a dados, que tem sido adotada em muitos projetos, incluindo OpenAPI (Documentação - Swagger), Docker, Kubernetes, entre outros. YAML era originalmente um acrônimo para 'Yet Another Markup Language' (Mais uma linguagem de marcação), mas agora é mais comumente referido como 'YAML Ain't Markup Language' (Ainda não é uma linguagem de marcação). Por isso se tornou também a linguagem utilizada pelo Github Actions para criar o Workflow, ou seja, o arquivo onde serão armazenadas as configurações do nosso Workflow será um arquivo yml.
52 |
53 | Documentos YAML são basicamente uma coleção de pares chave-valor onde o valor pode ser tão simples quanto uma string. Aqui estão algumas notas sobre a sintaxe YAML:
54 |
55 | - A indentação é usada para denotar a estrutura.
56 | - Tabs não são permitidas
57 | - A quantidade de espaço em branco não importa
58 | - O nó filho obrigatoriamente deve estar mais recuado que o nó pai.
59 |
60 | **Exemplo:**
61 |
62 | ```yaml
63 | # Strings não requerem aspas duplas ou simples (Opcional)
64 | titulo: Introdução a YAML
65 |
66 | # Strings com multiplas linhas obrigatoriamente são inicializadas com |
67 | execute: |
68 | npm ci
69 | npm build
70 | npm test
71 |
72 | # Inteiros
73 | idade: 29
74 |
75 | # Float:
76 | preco: 15.99
77 |
78 | # Boolean aceita duas formas
79 | publicado: false
80 | publicado: FALSE
81 |
82 | # Nulo aceita várias formas
83 | publicado:
84 | publicado: null
85 | publicado: Null
86 | publicado: NULL
87 |
88 | # Listas aceita 2 formatos
89 | numeros:
90 | - um
91 | - dois
92 | - tres
93 |
94 | numeros: [ um, dois, tres ]
95 |
96 | ```
97 |
98 |
99 |
100 |
Site Oficial: YAML
101 |
102 |
103 |
4. Palavras Chave do Github Actions
104 |
105 | Os arquivos do Github Actions são escritos usando a linguagem YAML. Na sequência, vamos entender como implementar os conceitos mais importantes no arquivo de fluxo de trabalho:
106 |
107 |
4.1. Name
108 |
109 | O nome do seu fluxo de trabalho que é exibido na página de ações do Github. Se você omitir esse campo, ele será definido como o nome do arquivo.
110 |
111 | **Exemplo:**
112 |
113 | ```yaml
114 | name: Pipeline CI-CD
115 | ```
116 |
117 | 4.2. on
118 |
119 | A palavra-chave **on** define os eventos do Github que acionam o fluxo de trabalho. Você pode fornecer um único evento ou um array de eventos que aciona um fluxo de trabalho.
120 |
121 | **Exemplo:**
122 |
123 | ```yaml
124 | on: push
125 | # ou
126 | on: [pull_request, issues]
127 | ```
128 |
129 | 4.3. jobs
130 |
131 | A execução de um fluxo de trabalho é composta por um ou mais trabalhos. Os trabalhos definem a funcionalidade que será executada no fluxo de trabalho e executada em paralelo por padrão.
132 |
133 | **Exemplo:**
134 |
135 | ```yaml
136 | jobs:
137 | my-job:
138 | name: My Job
139 | runs-on: ubuntu-latest
140 | steps:
141 | - name: Imprimir uma saudação
142 | run: |
143 | echo Olá!
144 | ```
145 |
146 | 4.4. Env
147 |
148 | A palavra chave Env define um conjunto de variáveis de ambiente, que estão disponíveis para todos os trabalhos e etapas do fluxo de trabalho. Você também pode definir variáveis de ambiente que estão disponíveis apenas para uma tarefa ou etapa.
149 |
150 | **Exemplo:**
151 |
152 | ```yaml
153 | env:
154 | CI: true
155 | ```
156 |
157 | 4.5. Runs-on
158 |
159 | É importante executar seus fluxos de trabalho nos ambientes certos para garantir que eles sejam bem-sucedidos nas circunstâncias de produção. Através da palavra chave Runs-on você pode definir as versões de sistema operacional e software em que seu fluxo de trabalho será executado.
160 |
161 | **Exemplo:**
162 |
163 | ```yaml
164 | run-on: ubuntu-latest
165 | ```
166 |
167 | 4.6. Steps
168 |
169 | Agrupa todas as etapas executadas na tarefa. Cada item aninhado nesta seção é uma ação da tarefa.
170 |
171 | **Exemplo:**
172 |
173 | ```yaml
174 | steps:
175 | - run: echo "Iniciando o Build da Aplicação"
176 | - uses: actions/checkout@v3
177 | - name: Setup JDK 17
178 | uses: actions/setup-java@v3
179 | with:
180 | java-version: 17
181 | distribution: 'adopt'
182 | ```
183 |
184 | Você deve usar a ação de actions/checkout@v3 sempre que seu fluxo de trabalho for executado no código do repositório.
185 |
186 | 4.7. Uses
187 |
188 | A palavra-chave Uses especifica que esta etapa executará uma versão específica de uma ação. Esta é uma ação que verifica seu repositório no executor, permitindo que você execute scripts ou outras ações em seu código (como ferramentas de teste).
189 |
190 | **Exemplo:**
191 |
192 | ```yaml
193 | uses: actions/setup-java@v3
194 | ```
195 |
196 | 4.8. With
197 |
198 | A palavra-chave With indica a versão especifica que deve ser instalada de um determinado software.
199 |
200 | **Exemplo:**
201 |
202 | ```yaml
203 | uses: actions/setup-java@v3
204 | with:
205 | java-version: 17
206 | distribution: 'adopt'
207 | ```
208 |
209 |
210 |
211 |
Documentação: Github Actions
212 |
213 |
214 |
215 |
216 |
217 |
--------------------------------------------------------------------------------
/05_devops/solid.md:
--------------------------------------------------------------------------------
1 |
Introdução ao SOLID
2 |
3 |
4 |
5 | Aprender Orientação a Objetos não nos previne de escrever um **código confuso** ou, pior ainda, um software complexo, não preparado para crescer e/ou receber manutenção de forma simples. Escrever um bom código, usando de maneira correta os conceitos da Orientação a Objetos requer muita prática e experiência. Felizmente, muitos projetistas de software documentam o que chamamos de padrões de projeto, que nada mais são do que as famosas "Boas Práticas" de Orientação a Objetos para determinados problemas.
6 |
7 | Um grupo de princípios de desenvolvimento de software muito famoso entre as pessoas desenvolvedoras é o **SOLID**. Os **cinco princípios do SOLID** são guias de como podemos criar softwares Orientados a Objetos legíveis e sustentáveis. Eles serão apresentados na ordem das letras do acrônimo, entretanto é importante ressaltar que não existe uma ordem para entendê-los, muito menos para aplicá-los, ou uma regra que determina que os 5 princípios devem ser aplicados em todos os projetos, então fique a vontade para estudar na sua ordem de preferência.
8 |
9 |
1. O que é SOLID?
10 |
11 | **SOLID**, como citado anteriormente, são cinco princípios da programação Orientada a Objetos que facilitam no desenvolvimento de softwares, tornando-os fáceis de manter e estender. Esses princípios podem ser aplicados a qualquer linguagem Orientada a Objetos.
12 |
13 | Um ponto importante a ser destacado é que alguns deles podem parecer semelhantes, mas **não possuem a mesma finalidade**. Por exemplo, é possível satisfazer um princípio enquanto viola outro (mesmo que sejam parecidos), por isso em uma parte do projeto pode ser necessário aplicar um principio e em outra parte do projeto pode ser necessário aplicar outro.
14 |
15 |
16 |
17 |
1.2. A origem do acrônimo SOLID
18 |
19 | O SOLID é uma junção de **princípios e boas práticas que visam melhorar a** **arquitetura e design de um projeto**, além de ter como intuito facilitar sua manutenção e compreensão.
20 |
21 | O termo SOLID surgiu após seu criador, *Michael Feathers*, observar que era possível unificar os **cinco princípios da orientação a objeto na sigla SOLID**.
22 |
23 |
24 |
25 |
26 |
27 | O acrônimo SOLID significa:
28 |
29 |
30 |
31 | Esses princípios ajudam a pessoa desenvolvedora a escrever códigos mais limpos, separando responsabilidades, diminuindo acoplamentos, facilitando a refatoração e estimulando o reaproveitamento do código.
32 |
33 | > **Acoplamento** significa o quanto uma Classe depende da outra para funcionar. E quanto maior for esta dependência entre ambas, dizemos que as 2 Classes estão fortemente acopladas e quanto menor for esta dependência entre ambas, dizemos que as 2 Classes estão fracamente acopladas. O forte acoplamento traz muitos problemas, especialmente em relação a manutenção e o gerenciamento, pois qualquer mudança em uma Classe impacta diretamente a outra Classe, e às vezes até uma Cadeia de Classes.
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/05_devops/solid_01.md:
--------------------------------------------------------------------------------
1 |
2. SRP — Single Responsibility Principle
2 |
3 | Uma das bases da programação orientada a objetos é a **Coesão**. Uma classe é **coesa** quando ela é focada em uma responsabilidade bem definida, assim como também não tem responsabilidades além da sua. Se uma classe deve gerar uma nota fiscal, por exemplo, essa deve ser a única responsabilidade que ela deve ter e qualquer coisa além disso vai diminuir a sua coesão. A coesão nos trás uma série de vantagens:
4 |
5 | - **Facilidade de manutenção:** Uma vez que temos classes com uma única responsabilidade, saberemos quais classes afetam ou não uma funcionalidade, qual o escopo dessa classes e onde a manutenção e correções de bugs de uma determinada funcionalidade devem ser feitas;
6 | - **Menos código:** Com menos código, a legibilidade fica mais fácil e podemos ganhar tempo no entendimento do sistema;
7 | - **Reuso:** Uma vez que uma classe cuida de uma única responsabilidade, é fácil reusar sempre que quisermos essa mesma responsabilidade/funcionalidade no sistema.
8 |
9 | O **Princípio de Responsabilidade Única** reforça o uso da coesão, afirmando que uma classe que tem muitas responsabilidades, aumentam as possibilidades de ocorrerem *bugs* ao alterar uma de suas responsabilidades, sem que possamos perceber.
10 |
11 |
Uma classe deve ter um, e somente um, motivo para mudar.
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Esse princípio declara que uma classe deve ser especializada em um único assunto e possuir apenas uma responsabilidade dentro do software, ou seja, a classe deve ter uma única tarefa ou ação para executar.
20 |
21 | Quando estamos aprendendo Programação Orientada a Objetos, sem percebermos, damos a uma classe mais de uma responsabilidade e acabamos criando classes que fazem de tudo, as chamada **God Class** (Classe Deus). Num primeiro momento isso pode parecer eficiente, mas como as responsabilidades acabam se misturando, quando há necessidade de realizar alterações nessa classe, será difícil modificar uma dessas responsabilidades sem comprometer as outras. Toda alteração acaba sendo introduzida com um certo nível de incerteza em nosso sistema, principalmente se não existirem testes automatizados!
22 |
23 | > **God Class** ou **Classe Deus:** *Na Programação Orientada a Objetos, é uma classe que sabe demais ou faz demais.*
24 |
25 |

**Exemplo**:
26 |
27 | Vamos analisar a Classe **Livro**:
28 |
29 | ```java
30 | package solid_srp_v1;
31 |
32 | class Livro {
33 |
34 | String nome;
35 | String nomeAutor;
36 | int ano;
37 | double preco;
38 | String isbn;
39 |
40 | public Livro(String nome, String nomeAutor, int ano, double preco, String isbn) {
41 | this.nome = nome;
42 | this.nomeAutor = nomeAutor;
43 | this.ano = ano;
44 | this.preco = preco;
45 | this.isbn = isbn;
46 | }
47 |
48 | public String getNome() {
49 | return nome;
50 | }
51 |
52 | public void setNome(String nome) {
53 | this.nome = nome;
54 | }
55 |
56 | public String getNomeAutor() {
57 | return nomeAutor;
58 | }
59 |
60 | public void setNomeAutor(String nomeAutor) {
61 | this.nomeAutor = nomeAutor;
62 | }
63 |
64 | public int getAno() {
65 | return ano;
66 | }
67 |
68 | public void setAno(int ano) {
69 | this.ano = ano;
70 | }
71 |
72 | public double getPreco() {
73 | return preco;
74 | }
75 |
76 | public void setPreco(double preco) {
77 | this.preco = preco;
78 | }
79 |
80 | public String getIsbn() {
81 | return isbn;
82 | }
83 |
84 | public void setIsbn(String isbn) {
85 | this.isbn = isbn;
86 | }
87 |
88 | }
89 | ```
90 |
91 | Na Classe Livro estamos armazenando os Atributos e Métodos de um Objeto da Classe *Livro*.
92 |
93 | Agora, vamos criar a Classe Fatura, que terá a lógica para o faturamento e o cálculo do preço total de venda dos livros. Na Classe Fatura, vamos considerar que nossa loja vende apenas livros:
94 |
95 | ```java
96 | package solid_srp_v1;
97 |
98 | public class Fatura {
99 |
100 | private Livro livro;
101 | private int quantidade;
102 | private double porcDesconto;
103 | private double porcImposto;
104 | private double total;
105 |
106 | public Fatura(Livro livro, int quantidade, double porcDesconto, double porcImposto) {
107 | this.livro = livro;
108 | this.quantidade = quantidade;
109 | this.porcDesconto = porcDesconto;
110 | this.porcImposto = porcImposto;
111 | this.total = this.calcularTotal();
112 | }
113 |
114 | public Livro getLivro() {
115 | return livro;
116 | }
117 |
118 | public void setLivro(Livro livro) {
119 | this.livro = livro;
120 | }
121 |
122 | public int getQuantidade() {
123 | return quantidade;
124 | }
125 |
126 | public void setQuantidade(int quantidade) {
127 | this.quantidade = quantidade;
128 | }
129 |
130 | public double getPorcDesconto() {
131 | return porcDesconto;
132 | }
133 |
134 | public void setPorcDesconto(double porcDesconto) {
135 | this.porcDesconto = porcDesconto;
136 | }
137 |
138 | public double getPorcImposto() {
139 | return porcImposto;
140 | }
141 |
142 | public void setPorcImposto(double porcImposto) {
143 | this.porcImposto = porcImposto;
144 | }
145 |
146 | public double getTotal() {
147 | return total;
148 | }
149 |
150 | public void setTotal() {
151 | this.total = this.calcularTotal();
152 | }
153 |
154 | public double calcularTotal() {
155 | double preco = ((livro.preco - livro.preco * porcDesconto) * this.quantidade);
156 |
157 | double precoComImposto = preco * (1 + porcImposto);
158 |
159 | return precoComImposto;
160 | }
161 |
162 | public void imprimirFatura() {
163 | System.out.println(quantidade + "x " + livro.nome + " " + livro.preco + "$");
164 | System.out.println("Porcentagem de desconto: " + porcDesconto);
165 | System.out.println("Procentagem de imposto: " + porcImposto);
166 | System.out.println("Total: " + total);
167 | }
168 |
169 | }
170 | ```
171 |
172 | A Classe Fatura contém um Objeto da Classe Livro, alguns Atributos relativos ao faturamento e 2 Métodos especializados:
173 |
174 | - Método **calcularTotal**, que calcula o preço total;
175 | - Método **imprimirFatura**, que imprime a fatura no console.
176 |
177 | Neste exemplo, o Método **imprimirFatura**, que tem nossa lógica de impressão, viola o Principio da Responsabilidade Única. De acordo com o SRP, nossa Classe deve ter apenas uma única razão para ser alterada. Essa razão deve ser uma mudança no cálculo da fatura. Nessa arquitetura, no entanto, se quiséssemos mudar o formato de impressão, precisaríamos mudar a classe. É por isso que não devemos misturar a lógica de impressão com a lógica de negócios na mesma classe.
178 |
179 | Como podemos, então, consertar esse problema?
180 |
181 | Podemos criar novas classes para a lógica de impressão, para não precisarmos mais modificar a classe Fatura para esses fins. Vamos criar a Classe **ImpressaoDeFatura** e movermos o método para ela:
182 |
183 | ```java
184 | package solid_srp_v2;
185 |
186 | public class ImpressaoDeFatura {
187 |
188 | private Fatura fatura;
189 |
190 | public ImpressaoDeFatura(Fatura fatura) {
191 | this.fatura = fatura;
192 | }
193 |
194 | public void imprimir() {
195 | System.out.println(fatura.getQuantidade() + "x " + fatura.getLivro().getNome()
196 | + " R$ " + fatura.getLivro().getPreco());
197 | System.out.println("Porcentagem de desconto: " + fatura.getPorcDesconto());
198 | System.out.println("Procentagem de imposto: " + fatura.getPorcImposto());
199 | System.out.println("Total: " + fatura.getTotal());
200 | }
201 |
202 | }
203 | ```
204 |
205 | A nossa Classe **Fatura** ficará da seguinte forma:
206 |
207 | ```java
208 | package solid_srp_v2;
209 |
210 | public class Fatura {
211 |
212 | private Livro livro;
213 | private int quantidade;
214 | private double porcDesconto;
215 | private double porcImposto;
216 | private double total;
217 |
218 | public Fatura(Livro livro, int quantidade, double porcDesconto, double porcImposto) {
219 | this.livro = livro;
220 | this.quantidade = quantidade;
221 | this.porcDesconto = porcDesconto;
222 | this.porcImposto = porcImposto;
223 | this.total = this.calcularTotal();
224 | }
225 |
226 | public Livro getLivro() {
227 | return livro;
228 | }
229 |
230 | public void setLivro(Livro livro) {
231 | this.livro = livro;
232 | }
233 |
234 | public int getQuantidade() {
235 | return quantidade;
236 | }
237 |
238 | public void setQuantidade(int quantidade) {
239 | this.quantidade = quantidade;
240 | }
241 |
242 | public double getPorcDesconto() {
243 | return porcDesconto;
244 | }
245 |
246 | public void setPorcDesconto(double porcDesconto) {
247 | this.porcDesconto = porcDesconto;
248 | }
249 |
250 | public double getPorcImposto() {
251 | return porcImposto;
252 | }
253 |
254 | public void setPorcImposto(double porcImposto) {
255 | this.porcImposto = porcImposto;
256 | }
257 |
258 | public double getTotal() {
259 | return total;
260 | }
261 |
262 | public void setTotal() {
263 | this.total = this.calcularTotal();
264 | }
265 |
266 | public double calcularTotal() {
267 | double preco = ((livro.preco - livro.preco * porcDesconto) * this.quantidade);
268 |
269 | double precoComImposto = preco * (1 + porcImposto);
270 |
271 | return precoComImposto;
272 | }
273 |
274 | }
275 | ```
276 |
277 |
278 | Observe que além de desenvolvermos uma Classe que alivia a Classe *Fatura* de suas funções de Impressão, também poderemos aproveitar a Classe *ImpressaoDeFatura* para imprimir a fatura em outras mídias porque temos uma Classe separada e dedicada a essa preocupação.
279 |
280 |
281 |
282 |
Código fonte: Projeto - Livraria
283 |
284 |
285 |
286 |
287 |
288 |
--------------------------------------------------------------------------------
/05_devops/solid_02.md:
--------------------------------------------------------------------------------
1 |
3. OCP — Open-Closed Principle
2 |
3 | Software é um **produto evolutivo**, e raramente é feito uma única vez e nunca mais será modificado. Sendo assim, nosso software deve conseguir evoluir a medida que as **demandas por novas funcionalidade** crescem. Porém, como essas evoluções devem vir, por meio de alterações ou extensões?
4 |
5 | O **Princípio de Aberto/Fechado** diz que:
6 |
7 |
Objetos ou Entidades devem estar abertos para extensão, mas fechados para modificação.
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Simplificando, quando novos comportamentos e recursos precisam ser adicionados no software, devemos estender e não alterar o código fonte original. A **extensibilidade** é uma das chaves da orientação a objetos. Quando um novo comportamento ou funcionalidade precisa ser adicionado, espera-se que as existentes sejam **estendidas** e não alteradas, dessa forma o código original permanece **intacto e confiável** enquanto as novas são implementadas através de extensibilidade.
16 |
17 | As principais vantagens de utilizar o princípio aberto/fechado são:
18 |
19 | - **Facilidade de manutenção do código**, já que cada classe possui uma responsabilidade única;
20 | - **Contribui para a arquitetura sustentável do projeto**, possibilitando evoluções sem comprometer outras funcionalidades do projeto.
21 |
22 |
23 |
24 |

**Exemplo:**
25 |
26 | Vamos explorar o conceito do princípio aberto/fechado através do exemplo anterior (Livraria). Vamos criar uma Classe para salvar as nossas faturas em um banco de dados, onde possamos fazer pesquisas facilmente e Salvar em um arquivo PDF, para ser compartilhado.
27 |
28 | Sem pensar muito, Criamos uma nova Classe chamada **PersistenciaDaFatura** e adicionamos um Método para persistir a fatura no banco de dados e um outro Método para salvar em PDF, como vemos no código abaixo:
29 |
30 | ```java
31 | package solid_srp_v1;
32 |
33 | public class PersistenciaDaFatura {
34 |
35 | Fatura fatura;
36 |
37 | public PersistenciaDaFatura(Fatura fatura) {
38 | this.fatura = fatura;
39 | }
40 |
41 | public void salvarParaArquivoPdf(String nomeArquivo) {
42 | System.out.println("Salvar a fatura no arquivo: " + nomeArquivo);
43 | }
44 |
45 | public void salvarParaBancoDeDados() {
46 | System.out.println("Salvar a fatura no banco de dados");
47 | }
48 |
49 | }
50 | ```
51 |
52 | Infelizmente da forma que criamos a Classe **PersistenciaDaFatura** ela não é extensível no futuro, desta forma, para adicionarmos novas formas de persistência, seriamos obrigados a modificar a classe **PersistenciaDaFatura**, violando o princípio aberto/fechado. Se a nossa classe fosse criada obedecendo o princípio aberto/fechado, não precisaríamos alterar essa classe.
53 |
54 | Para corrigir o problema, vamos refatorar o código para que possamos atender ao princípio aberto/fechado. Primeiro, vamos alterar Classe **PersistenciaDaFatura** para uma Interface e adicionarmos um método de salvamento.
55 |
56 | ```java
57 | public interface PersistenciaDaFatura {
58 |
59 | public void salvar(Fatura fatura);
60 | }
61 | ```
62 |
63 | Na sequência vamos criar uma Classe de persistência para o banco de dados chamada **PersistenciaEmBD** e uma Classe de persistência para um arquivo PDF chamada **PersistenciaEmPDF**, que implementarão a Interface **PersistenciaDaFatura**:
64 |
65 | ```java
66 | package solid_ocp_v2;
67 |
68 | public class PersistenciaEmBD implements PersistenciaDaFatura{
69 |
70 | public Fatura fatura;
71 |
72 | public PersistenciaEmBD(Fatura fatura) {
73 | this.fatura = fatura;
74 | }
75 |
76 | public Fatura getFatura() {
77 | return fatura;
78 | }
79 |
80 | public void setFatura(Fatura fatura) {
81 | this.fatura = fatura;
82 | }
83 |
84 | @Override
85 | public void salvar(Fatura fatura) {
86 |
87 | System.out.println("Salvar a fatura no Banco de dados...\n");
88 | this.fatura.imprimirFatura();
89 |
90 | }
91 |
92 | }
93 | ```
94 |
95 |
96 |
97 | ```java
98 | package solid_ocp_v2;
99 |
100 | public class PersistenciaEmArquivoPdf implements PersistenciaDaFatura{
101 |
102 | public Fatura fatura;
103 |
104 | public PersistenciaEmArquivoPdf(Fatura fatura) {
105 | this.fatura = fatura;
106 | }
107 |
108 | public Fatura getFatura() {
109 | return fatura;
110 | }
111 |
112 | public void setFatura(Fatura fatura) {
113 | this.fatura = fatura;
114 | }
115 |
116 | @Override
117 | public void salvar(Fatura fatura) {
118 |
119 | System.out.println("Salvar a fatura no Arquivo PDF...\n");
120 | this.fatura.imprimirFatura();
121 |
122 | }
123 |
124 | }
125 | ```
126 |
127 |
128 |
129 | Agora, nossa lógica de persistência é facilmente extensível. Se precisarmos persistir em outro banco de dados, podemos fazer isso facilmente criando uma nova Classe que implementará a Interface **PersistenciaDaFatura**. Veja o Diagrama de Classes abaixo:
130 |
131 | ```mermaid
132 | classDiagram
133 | class PersistenciaDaFatura{
134 | << Interface >>
135 | }
136 | Livro <-- Fatura : Tem um Livro
137 | Fatura <.. PersistenciaDaFatura : Depende de
138 | PersistenciaDaFatura <|.. PersistenciaDaFaturaEmBD : Implementa
139 | PersistenciaDaFatura <|.. PersistenciaDaFaturaEmArquivoPdf : Implementa
140 | ```
141 |
142 | Essa é a flexibilidade que a Interface nos oferece, através do Polimorfismo.
143 |
144 |
145 |
146 |
Código fonte: Projeto - Livraria
147 |
148 |
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/05_devops/solid_04.md:
--------------------------------------------------------------------------------
1 |
5. ISP — Interface Segregation Principle
2 |
3 | Na Orientação a Objetos, quando falamos de **Interface**, estamos falando do conjunto de métodos que um objeto expõe, ou seja, das maneiras como nós podemos interagir com esse objeto. Toda mensagem (ou chamada de método) que um objeto recebe constitui uma interface.
4 |
5 | A interface funciona como um **contrato**: nós definimos o comportamento da interface na forma de diferentes métodos que ela possui. Cada classe que desejar compartilhar o comportamento dessa interface precisa **implementar** os métodos dela, ou seja, declarar como esses métodos serão executados. Quando a classe utiliza uma interface, na prática ela **assina o contrato** dizendo que **irá implementar todos os métodos dessa interface**.
6 |
7 | O Princípio da Segregação da Interface nos diz que:
8 |
9 |
Uma classe não deve ser forçada a implementar interfaces e métodos que não irão utilizar.
10 |
11 |
12 |
13 |
14 |
15 | Esse princípio basicamente diz que é melhor criar interfaces mais específicas ao invés de termos uma única interface genérica, onde as Classes não precisarão implementar Métodos que não serão utilizados.
16 |
17 |
18 |
19 |

**Exemplo:**
20 |
21 | Vamos explorar o conceito da princípio Segregação da Interface através do exemplo anterior (RH). Vamos alterar a Classe **Funcionario**, adicionando 2 Métodos abstratos: **calcularComissao()** e **calcularBonus()**, como vemos no código abaixo:
22 |
23 | ```java
24 | package solid_lsp_v1;
25 |
26 | public abstract class Funcionario {
27 |
28 | private float salario;
29 | private String cargo;
30 | private String nome;
31 |
32 | public Funcionario(float salario, String cargo, String nome) {
33 | this.salario = salario;
34 | this.cargo = cargo;
35 | this.nome = nome;
36 | }
37 |
38 | //Métodos abstratos
39 | abstract float calcularSalario();
40 | abstract float calcularComissao();
41 | abstract float calcularBonus();
42 |
43 | public float getSalario() {
44 | return salario;
45 | }
46 |
47 | public void setSalario(float salario) {
48 | this.salario = salario;
49 | }
50 |
51 | public String getCargo() {
52 | return cargo;
53 | }
54 |
55 | public void setCargo(String cargo) {
56 | this.cargo = cargo;
57 | }
58 |
59 | public String getNome() {
60 | return nome;
61 | }
62 |
63 | public void setNome(String nome) {
64 | this.nome = nome;
65 | }
66 |
67 | }
68 | ```
69 |
70 | Estes 2 Métodos serão utilizados como Métodos auxiliares do Método **calcularSalario()**, porque a nossa empresa criou um novo cargo: **Atendente de caixa**, como vemos no código abaixo:
71 |
72 | ```java
73 | package solid_lsp_v1;
74 |
75 | public class AtendenteCaixa extends Funcionario {
76 |
77 | public AtendenteCaixa(float salario, String cargo, String nome) {
78 | super(salario, cargo, nome);
79 | }
80 |
81 | // Método Calcular Salário
82 | @Override
83 | float calcularSalario() {
84 | return this.getSalario();
85 | }
86 |
87 | // Método Calcular Comissão - Não Implementado
88 | @Override
89 | float calcularComissao() {
90 | return 0.0f;
91 | }
92 |
93 | // Método Calcular Bônus - Não Implmentado
94 | @Override
95 | float calcularBonus() {
96 | return 0.0f;
97 | }
98 |
99 | }
100 | ```
101 |
102 | Observe que os Métodos novos foram inseridos na Classe, mas não retornam nada porquê o Atendente de Caixa não possui comissão e bônus, mas por se tratarem de Métodos abstratos, eles devem ser obrigatoriamente implementados. Vamos observar as Classes **Gerente** e **Vendedor**:
103 |
104 | ```java
105 | package solid_lsp_v1;
106 |
107 | class Gerente extends Funcionario {
108 |
109 | private float bonus;
110 |
111 | public Gerente(float salario, String cargo, String nome, float bonus) {
112 | super(salario, cargo, nome);
113 | this.bonus = bonus;
114 | }
115 |
116 | public float getBonus() {
117 | return bonus;
118 | }
119 |
120 | public void setBonus(float bonus) {
121 | this.bonus = bonus;
122 | }
123 |
124 | // Método Calcular Salário
125 | @Override
126 | public float calcularSalario(){
127 | return this.getSalario() + this.calcularBonus();
128 | }
129 |
130 | // Método Calcular Comissão - Não Implmentado
131 | @Override
132 | float calcularComissao() {
133 | return 0.0f;
134 | }
135 |
136 | // Método Calcular Bônus
137 | @Override
138 | float calcularBonus() {
139 | return this.getSalario() * this.getBonus();
140 | }
141 |
142 | }
143 | ```
144 |
145 |
146 |
147 | ```java
148 | package solid_lsp_v1;
149 |
150 | class Vendedor extends Funcionario {
151 |
152 | private float totalVendas;
153 |
154 | public Vendedor(float salario, String cargo, String nome, float totalVendas) {
155 | super(salario, cargo, nome);
156 | this.totalVendas = totalVendas;
157 | }
158 |
159 | public float getTotalVendas() {
160 | return totalVendas;
161 | }
162 |
163 | public void setTotalVendas(float totalVendas) {
164 | this.totalVendas = totalVendas;
165 | }
166 |
167 | // Método Calcular Salário
168 | @Override
169 | public float calcularSalario() {
170 | return this.getSalario() + this.calcularComissao();
171 | }
172 |
173 | // Método Calcular Comissão
174 | @Override
175 | float calcularComissao() {
176 | return this.totalVendas * 0.1f;
177 | }
178 |
179 | // Método Calcular Bônus - Não Implmentado
180 | @Override
181 | float calcularBonus() {
182 | return 0.0f;
183 | }
184 | }
185 | ```
186 |
187 | Observe que os Métodos novos foram inseridos nas duas Classes, por se tratarem de Métodos abstratos, eles devem ser obrigatoriamente implementados. Na Classe **Gerente** foi implementado o Método **calcularBonus()** e na Classe **Vendedor** foi implementado o Método **calcularComissao()**.
188 |
189 | Com isso temos vários problemas de Design:
190 |
191 | - O primeiro é que apenas o Gerente recebe bônus e Vendedor e Atendente de Caixa estão sendo obrigados a implementar o Método **calcularBonus()**.
192 | - O segundo é que apenas o Vendedor recebe comissão e Gerente e Atendente de Caixa estão sendo obrigados a implementar o Método **calcularComissao()**.
193 | - O terceiro é que o Atendente de Caixa não recebe comissão e bônus, e está sendo obrigado a implementar os Métodos **calcularBonus()** e **calcularComissao()**.
194 |
195 | Aplicando o Princípio da Segregação de Interfaces, vamos fazer uma refatoração no código, e criar 2 Interfaces: **Comissionavel** e **BonusAplicavel**, que terão em suas assinaturas os respectivos métodos **calcularBonus()** e **calcularComissao()**:
196 |
197 | ```java
198 | package solid_lsp_v2;
199 |
200 | public interface Comissionavel{
201 |
202 | public float calcularComissao();
203 |
204 | }
205 | ```
206 |
207 |
208 |
209 | ```java
210 | package solid_lsp_v2;
211 |
212 | public interface BonusAplicavel{
213 |
214 | public float calcularBonus();
215 |
216 | }
217 | ```
218 |
219 |
220 |
221 | Na sequência, vamos implementar a Interface **BonusAplicavel na Classe Gerente a Interface**, a interface **Comissionavel na Classe Vendedor** e limpar a Classe **AtendenteCaixa**:
222 |
223 | ```java
224 | package solid_lsp_v2;
225 |
226 | public class Gerente extends Funcionario implements BonusAplicavel {
227 |
228 | private float bonus;
229 |
230 | public Gerente(float salario, String cargo, String nome, float bonus) {
231 | super(salario, cargo, nome);
232 | this.bonus = bonus;
233 | }
234 |
235 | public float getBonus() {
236 | return bonus;
237 | }
238 |
239 | public void setBonus(float bonus) {
240 | this.bonus = bonus;
241 | }
242 |
243 | // Método Calcular Salário - Classe Funcionario
244 | @Override
245 | public float calcularSalario() {
246 | return this.getSalario() + this.calcularBonus();
247 | }
248 |
249 | // Método Calcular Bônus - Interface BonusAplicavel
250 | @Override
251 | public float calcularBonus() {
252 | return this.getSalario() * this.getBonus();
253 | }
254 | }
255 |
256 | ```
257 |
258 |
259 |
260 | ```java
261 | package solid_lsp_v2;
262 |
263 | class Vendedor extends Funcionario implements Comissionavel{
264 |
265 | private float totalVendas;
266 |
267 | public Vendedor(float salario, String cargo, String nome, float totalVendas) {
268 | super(salario, cargo, nome);
269 | this.totalVendas = totalVendas;
270 | }
271 |
272 | public float getTotalVendas() {
273 | return totalVendas;
274 | }
275 |
276 | public void setTotalVendas(float totalVendas) {
277 | this.totalVendas = totalVendas;
278 | }
279 |
280 | // Método Calcular Salário - Classe Funcionario
281 | @Override
282 | public float calcularSalario(){
283 | return this.getSalario() + this.calcularComissao();
284 | }
285 |
286 | // Método Calcular Comissão - Interface Comissionavel
287 | @Override
288 | public float calcularComissao() {
289 | return this.totalVendas * 0.1f;
290 | }
291 |
292 | }
293 | ```
294 |
295 |
296 |
297 | ```java
298 | package solid_lsp_v2;
299 |
300 | public class AtendenteCaixa extends Funcionario{
301 |
302 |
303 | public AtendenteCaixa(float salario, String cargo, String nome) {
304 | super(salario, cargo, nome);
305 | }
306 |
307 | // Método Calcular Salário - Classe Funcionario
308 | @Override
309 | float calcularSalario() {
310 | return this.getSalario();
311 | }
312 |
313 | }
314 | ```
315 |
316 | Agora nossas Classes **Gerente** e **Vendedor** e **AtendenteCaixa** estão implementando apenas os Métodos que serão realmente utilizados.
317 |
318 | O princípio da Segregação de Interfaces nos ajuda a aumentar a granularidade de nossos objetos, aumentando a coesão de suas interfaces e diminuindo drasticamente o acoplamento. E isso melhora a manutenção do nosso código, pois interfaces mais simples são mais fáceis de serem entendidas e implementadas.
319 |
320 |
321 |
322 |
Código fonte: Projeto - RH
323 |
324 |
325 |
326 |
327 |
--------------------------------------------------------------------------------
/05_devops/solid_05.md:
--------------------------------------------------------------------------------
1 |
6. DIP — Dependency Inversion Principle
2 |
3 | O **Princípio de inversão de dependência** é comumente separado em dois conceitos principais que o definem:
4 |
5 | - **Módulos de alto nível não devem depender dos módulos de baixo nível**. Os dois devem ser baseados em abstrações.
6 | - **Abstrações não devem ser baseadas em detalhes**. Detalhes devem ser baseados em abstrações.
7 |
8 | O Princípio da Inversão de Dependência nos diz que:
9 |
10 |
Nossas Classes devem depender de abstrações e não de implementações.
As Abstrações não devem ser baseadas em detalhes.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | O princípio de inversão de dependência inverte a maneira como pensamos o nosso design de software, nos induzindo a fazer com que tanto nossos módulos de alto nível quanto os de baixo nível dependam de uma mesma abstração.
19 |
20 | Em um esquema tradicional de desenvolvimento de software, os componentes de nível inferior são projetados para serem consumidos por módulos de nível superior, de modo que estes possam ir incrementando de complexidade conforme o sistema vai sendo construído.
21 |
22 | Neste modelo arquitetural, os componentes da camada superior dependem dos componentes mais baixos apenas para que possam realizar alguma tarefa, isto reduz as possibilidades de reuso dos componentes de alto nível, devido ao excessivo acoplamento entre os componentes.
23 |
24 | No contexto da programação orientada a objetos, é comum que as pessoas confundam a *Inversão de Dependência* com a *Injeção de Dependência*, porém são coisas distintas, mas que relacionam entre si com um proposito em comum, deixar o código desacoplado.
25 |
26 |
6.1. Construindo uma camada de abstração
27 |
28 | Para construir a Camada de Abstração, elemento fundamental do princípio de inversão de dependência, precisamos seguir alguns passos:
29 |
30 | 1. Todas as variáveis membro da classe devem ser Interfaces ou Classes Abstratas;
31 | 2. Todos os pacotes contendo classes concretas devem se comunicar somente através de Interfaces ou Classes Abstratas;
32 | 3. Nenhuma Classe deve derivar de uma outra Classe concreta;
33 | 4. Nenhum Método deve sobrescrever um Método já implementado;
34 | 5. Todas as instâncias de objetos devem ser criadas através de Padrões de Projetos de criação como a Injeção de Dependências.
35 |
36 |
37 |
38 |

**Exemplo**
39 |
40 | Vamos analisar as classes **FrontendDev** e **BackendDev**:
41 |
42 | ```java
43 | package solid_dip_v1;
44 |
45 | public class FrontendDev{
46 |
47 | public void react() {
48 | System.out.println("\nDesenvolvedor React");
49 | }
50 |
51 | }
52 | ```
53 |
54 |
55 |
56 | ```java
57 | package solid_dip_v1;
58 |
59 | public class BackendDev{
60 |
61 | public void java() {
62 | System.out.println("\nDesenvolvedor Java");
63 | }
64 |
65 | }
66 | ```
67 |
68 |
69 |
70 | As 2 Classes acima definem 2 tipos de pessoas Desenvolvedoras: Frontend e Backend.
71 |
72 | Na sequência, vamos analisar a Classe **ProjetoSoftware**:
73 |
74 | ```java
75 | package solid_dip_v1;
76 |
77 | public class ProjetoSoftware {
78 |
79 | public FrontendDev frontDev;
80 | public BackendDev backDev;
81 |
82 | public ProjetoSoftware(FrontendDev frontDev, BackendDev backDev) {
83 | this.frontDev = frontDev;
84 | this.backDev = backDev;
85 | }
86 |
87 | public void criarProjeto() {
88 | this.frontDev.react();
89 | this.backDev.java();
90 | }
91 | }
92 | ```
93 |
94 |
95 |
96 | Observe que a Classe **ProjetoSoftware** usa as Classes **FrontendDev** e **BackendDev** no seu processo de desenvolvimento.
97 |
98 | A Classe **ProjetoSoftware** é um módulo de **alto nível**, que da forma como foi implementada, ela depende dos módulos de **baixo nível**,ou seja, as Classes **BackendDev** e **FrontendDev**. Na prática, estamos violando a primeira parte do princípio de inversão de dependência.
99 |
100 | Ao inspecionar o Método **criarProjetos()** da Classe ProjetoSoftware, percebemos que os métodos **react()** e **java()** são métodos vinculados às Classes correspondentes. Quanto ao escopo do projeto, são detalhes, pois, em ambos os casos, são formas de desenvolvimento. Na prática, estamos violando a segunda parte do princípio de inversão de dependência.
101 |
102 | Para resolver esse problema, vamos implementar uma interface chamada IDev, como mostra o código abaixo:
103 |
104 | ```java
105 | package solid_dip_v2;
106 |
107 | public interface IDev {
108 |
109 | public void dev();
110 |
111 | }
112 | ```
113 |
114 | Observe que foi adicionado o Método **dev()** na Interface **IDev**. Na sequência, vamos modificar as Classes **BackendDev** e **FrontendDev**, para implementarem a Interface **IDev**:
115 |
116 | ```java
117 | package solid_dip_v2;
118 |
119 | public class FrontendDev implements IDev{
120 |
121 | @Override
122 | public void dev() {
123 | this.react();
124 |
125 | }
126 |
127 | public void react() {
128 | System.out.println("\nDesenvolvedor React");
129 | }
130 |
131 | }
132 |
133 | ```
134 |
135 |
136 |
137 | ```java
138 | package solid_dip_v2;
139 |
140 | public class BackendDev implements IDev{
141 |
142 | @Override
143 | public void dev() {
144 | this.java();
145 |
146 | }
147 |
148 | public void java() {
149 | System.out.println("\nDesenvolvedor Java");
150 | }
151 |
152 | }
153 | ```
154 |
155 | Observe que como as Classes **FrontendDev** e **BackendDev** são Classes semelhantes, implementamos a Interface **IDev** em ambas. A implementação da Interface obriga a implementar o Método dev(). Na implementação do Método dev(), inserimos a chamada do Método específico de cada Classe, **react()** e **java()** respectivamente, gerando assim uma abstração. Desta forma, resolvemos a segunda parte do princípio de inversão de dependência, que foi violado.
156 |
157 | O próximo passo, para resolver a violação da primeira parte, é refatorar a Classe **ProjetoSoftware** para que ela não dependa das Classes **FrontEndDev** e **BackendDev**, como mostra o código abaixo:
158 |
159 | ```java
160 | package solid_dip_v2;
161 |
162 | import java.util.List;
163 |
164 | public class ProjetoSoftware {
165 |
166 | public List
devs;
167 |
168 | public ProjetoSoftware(List devs) {
169 | this.devs = devs;
170 | }
171 |
172 | public void criarProjeto() {
173 | this.devs.forEach(d -> d.dev());
174 | }
175 | }
176 | ```
177 |
178 | Observe que ao invés de inicializar os Objetos das Classes **FrontendDev** e **BackendDev** de uma única maneira dentro da Classe **ProjetoSoftware**, nós transformamos os Objetos em uma Collection **List** do tipo **IDev**, para iterar através dos Objetos e chamar o Método **dev()** de cada Objeto das Classes **FrontEndDev** e **BackendDev**, criando uma abstração. Desta forma, resolvemos a primeira parte do princípio de inversão de dependência, que foi violado.
179 |
180 | O resultado é que a Classe ProjetoSoftware não depende de módulos de nível inferior (Classes **FrontendDev** e **BackendDev**), mas sim de abstrações e além disso, os módulos de baixo nível e seus detalhes dependem apenas de abstrações.
181 |
182 |
183 |
184 |
Código fonte: Projeto de Software
185 |
186 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/05_devops/tdd.md:
--------------------------------------------------------------------------------
1 |
Introdução ao TDD - Test Driven Development
2 |
3 |
4 |
5 | **Test Driven Development (TDD)** ou **Teste Guiado pelo Desenvolvimento**, tornou-se uma das práticas mais populares entre as pessoas desenvolvedoras de software. O conceito é muito simples: **Escreva seus testes antes mesmo de escrever o código de produção**.
6 |
7 | Mas por quê a ideia parece ser tão boa? Ao escrever os testes antes, a pessoa desenvolvedora garante que boa parte do seu sistema tem um teste que garante o seu funcionamento. Além disso, muitas pessoas desenvolvedoras também afirmam que os testes os guiam no projeto das classes do sistema.
8 |
9 | Antes de compreendermos como funciona, embora o conceito do TDD seja muito simples, é importante ressaltar que ele se baseia em 3 princípios fundamentais:
10 |
11 | > 1. *Você deve escrever um teste com falha antes de escrever qualquer código de produção.*
12 | >
13 | > 2. *Você não deve escrever apenas um teste, que seja suficiente para o código falhar ou provocar um erro de compilação.*
14 | >
15 | > 3. *Você não deve escrever mais código de produção do que o suficiente para fazer o teste com falha no momento passar.*
16 |
17 | Não aplicar estes 3 princípios fundamentais ao escrever os seus testes, indica que você está aplicando o TDD de forma incorreta.
18 |
19 |
20 |
21 |
1. Qual a diferença entre fazer TDD e escrever os testes depois?
22 |
23 | A pessoa desenvolvedora quando cria um teste automatizado, obtém o feedback da aplicação através da execução do teste. A diferença é justamente na quantidade de feedback. Quando o desenvolvedor escreve os testes somente ao finalizar a implementação do código de produção, ele passou muito tempo sem retorno. Afinal, escrever o código de produção leva tempo. Ao praticar o TDD, a pessoa desenvolvedora divide seu trabalho em pequenas etapas. Ela escreve um pequeno teste e implementa um pequeno pedaço da funcionalidade. E repete. A cada teste escrito, o desenvolvedor ganha feedback naquele momento.
24 |
25 | Quando se tem muito código já escrito, mudanças podem ser trabalhosas e custar caro. Ao contrário, quanto menos código escrito, menor será o custo da eventual mudança. E é justamente isso que acontece com os praticantes de TDD: eles recebem feedback no momento em que mudar ainda é barato.
26 |
27 | A figura abaixo exemplifica a diferença entre a quantidade de feedback de um desenvolvedor que pratica TDD e de um desenvolvedor que escreve testes ao final.
28 |
29 |

30 |
31 | A questão é que ao escrever os testes primeiro e esforçar-se para mantê-los fáceis de escrever, você está fazendo três coisas importantes no seu projeto:
32 |
33 | 1. Você está criando documentação e as especificações do projeto nunca ficarão desatualizadas.
34 | 2. Você está (re)projetando seu código, mantendo simples e facilmente testável, e isso o torna limpo, descomplicado, fácil de entender e de modificar.
35 | 3. Você está criando uma rede de segurança para fazer mudanças com a confiança de já ter realizado diversos testes.
36 |
37 |
38 |
39 | |

|
**ATENÇÃO:** *Os testes do Projeto Blog Pessoal foram criados no final do projeto por questões didáticas. No Mundo Real, geralmente os testes caminham junto com o projeto. *
|
40 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
41 |
42 |
43 |
44 |
2. A História do TDD
45 |
46 | O TDD ficou bastante popular após a publicação do livro TDD: By Example (Kent Beck - 2002). O próprio Kent afirma que TDD não foi uma ideia totalmente original. Ele conta que em algum momento de sua vida, ele leu em algum dos livros de seu pai (que era uma pessoa desenvolvedora), sobre uma técnica de testes mais antiga, onde a pessoa desenvolvedora colocava na fita (meio de armazenamento de dados, muito comum nos anos 60 e 70), o valor que ele esperava daquele programa, e então a pessoa desenvolvedora implementava o código até chegar naquele valor.
47 |
48 | Ele próprio conta que achou a ideia absurda. Qual o sentido de escrever um teste que falha? Mas resolveu experimentar. Após a experiência, ele disse que “*as pessoas sempre diziam conseguir separar o que o programa deve fazer, da sua implementação final, mas o que ele não sabia como fazer, até aquele momento em que resolveu escrever o teste antes.*”
49 |
50 | Daquele momento em diante, Kent continuou a trabalhar neste conceito. Em 1994, ele escreveu o seu primeiro framework de testes de unidade, o SUnit, (linguagem Smalltalk). Em 1995, ele apresentou o TDD pela primeira vez na OOPSLA - **Object-Oriented Programming, Systems, Languages & Applications**, que é uma conferência muito famosa da área de computação, já que muitas novidades tendem a aparecer lá.
51 |
52 | No ano 2000, o JUnit surgiu e Kent Beck, junto com Erich Gamma, publicou o artigo chamado de *“Test Infected”*, que mostrava as vantagens de se ter testes automatizados e como isso pode ser viciante. Finalmente em 2002, Kent Beck lançou seu livro sobre isso, e desde então a prática tem se tornado cada vez mais popular entre as pessoas desenvolvedoras.
53 |
54 |
55 |
56 |
3. Como o TDD funciona?
57 |
58 | O TDD na prática é muito simples:
59 |
60 | 1. Escreva um teste que falha;
61 |
62 | 2. Escreva o código da forma o mais simples possível;
63 |
64 | 3. Faça-o passar no teste;
65 |
66 | 4. Refatore (melhore) o código;
67 |
68 | 5. Teste novamente.
69 |
70 |
71 |
72 | Na imagem abaixo, podemos visualizar de forma gráfica o Ciclo do TDD, conhecido como o **Ciclo Vermelho-Verde-Azul (Refatora)**.
73 |
74 |

75 |
76 | Sempre que uma pessoa desenvolvedora recebe uma nova funcionalidade (feature) para implementar, ela geralmente encontra dificuldades nas pequenas tarefas. Tarefas essas que exigem a escrita de código. Classes são criadas, outras são modificadas para atender as novas necessidades. Todas essas modificações tem um propósito claro. Todo código escrito tem um objetivo.
77 |
78 | Ao praticar o TDD, a pessoa desenvolvedora, antes de começar a fazer essas modificações, deixa bem claro quais são os objetivos através de testes automatizados. **O teste em código nada mais é do que um trecho de código, que deixa claro o que determinado trecho de código deve fazer**.
79 |
80 | **Ao formalizar esse objetivo na forma de um teste automatizado, esse teste falhará porquê a funcionalidade ainda não foi implementada**. A pessoa desenvolvedora então trabalha para fazer esse teste passar.
81 |
82 | **Como?**
83 |
84 | **Implementando a funcionalidade!**
85 |
86 | Assim que o teste passar, a pessoa desenvolvedora então parte para uma próxima etapa no ciclo da busca pelo código de qualidade: **Refatorar!**
87 |
88 | > **Refatorar é melhorar o código que já está escrito**. É o processo de alterar um software de uma maneira que não mude o seu comportamento externo e ainda melhore a sua estrutura interna. É uma técnica disciplinada de limpar e organizar o código, e por consequência minimizar a chance de introduzir novos bugs.
89 |
90 | Durante a implementação de um código, a pessoa desenvolvedora está focada única e exclusivamente em implementar a funcionalidade, ou seja, fazer o código rodar. Raramente a pessoa desenvolvedora está pensando na qualidade do código. Por isso que, após a implementação da funcionalidade, a pessoa desenvolvedora começa a analisar como ela pode melhorar a qualidade do código, que já funciona e atende ao requisito do negócio. Após implementar as melhorias, será necessário executar novamente os testes, para garantir que tudo continua funcionando.
91 |
92 |
93 |
94 |
4. As Regras do TDD
95 |
96 | O Tio Bob (Robert C. Martin) definiu as regras do TDD no seu livro The Clean Coder (O código limpo).
97 |
98 | 1. Você não está autorizado a escrever qualquer código de produção a menos que seja para fazer um teste unitário falhado passar.
99 | 2. Você não está autorizado a escrever mais de um teste unitário do que é suficiente para falhar; e falhas de compilação são falhas.
100 | 3. Você não tem permissão para escrever mais código de produção do que o suficiente para passar no teste unitário falhado.
101 |
102 |
4.1 Por que seguir estas regras?
103 |
104 | Porque elas se destinam a facilitar sua vida!
105 |
106 | O objetivo das regras é manter as coisas concentradas em cada fase e evitar que você fique em ciclos e isso ajuda muito a manter as coisas claras em sua cabeça. Portanto:
107 |
108 | - Durante a fase vermelha (escrever o teste), trabalhe somente no código de teste. Um teste falhado é bom. Pelo menos se for o teste em que você está trabalhando. Todos os outros devem ser verdes.
109 | - Durante a fase verde (fazer o teste passar), trabalhe apenas no código de produção que fará o teste passar e não refatore nada. Se o teste que você acabou de escrever falhar, isso significa que sua implementação precisa funcionar. Se outros testes falharem, você quebrou a funcionalidade existente e precisa retroceder alguns passos.
110 | - Durante a fase azul (refatoração), somente refatore o código de produção e não faça nenhuma alteração funcional.
111 | Qualquer falha no teste significa que você quebrou a funcionalidade existente. Ou você não completou a refatoração, ou precisa recuar.
112 |
113 |
114 |
115 |
5. Quais são as vantagens de utilizar o TDD?
116 |
117 | Utilizar o TDD traz muitas vantagens para a pessoa desenvolvedora, entre elas podemos destacar:
118 |
119 | - Feedback rápido sobre a nova funcionalidade e sobre as outras funcionalidades existentes no sistema;
120 | - Código mais limpo, já que escrevemos códigos simples para o teste passar;
121 | - Segurança no Refatoramento pois podemos ver o que estamos ou não afetando;
122 | - Segurança na correção de bugs;
123 | - Maior produtividade já que o desenvolvedor encontra menos bugs e não desperdiça tempo com debugs;
124 | - Código da aplicação mais flexível, já que para escrever testes temos que separar em pequenos "pedaços" o nosso código, para que sejam testáveis, ou seja, nosso código estará menos acoplado.
125 |
126 |
127 |
128 |
6. Desvantagens do TDD
129 |
130 | Utilizar o TDD também tem as suas desvantagens, entre elas podemos destacar:
131 |
132 | - **O TDD não é uma fórmula mágica:** Os testes ajudam a localizar bugs, mas não encontram os bugs para você e muito menos resolverá todos os problemas do seu código;
133 | - **Processo lento:** Aplicar o TDD demanda mais tempo para escrever o código, tempo este que muitas vezes o time de desenvolvimento não tem;
134 | - **Todo o time de pessoas desenvolvedoras devem aplicar o TDD:** Como o TDD influencia o planejamento do código, é recomendado que todas as pessoas desenvolvedoras usem o TDD ou ninguém usa;
135 | - **Todos os testes devem ser mantidos quando os requisitos mudam:** Mesmo que os requisitos mudem, você não deve remover os testes. Simplesmente tem que alterar os testes primeiro e, em seguida, fazer os testes passarem, seguindo o Ciclo do TDD.
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
Bootcamp - Java Full Stack
5 |
6 |
Conteúdos
7 |
8 |
34 |
35 |
--------------------------------------------------------------------------------