├── 00_ambiente ├── 00_install_git.md ├── 01_install_java_17.md ├── 02_install_sts.md ├── 03_install_mysql.md ├── 04_uninstall_mysql.md ├── 05_install_Insomnia.md ├── 06_install_vscode.md ├── 07_install_node.md └── README.md ├── 01_http └── 01.md ├── 02_mysql ├── 01.md ├── 02.md ├── 03.md ├── 04.md ├── README.md └── der │ ├── loja_games.mwb │ ├── loja_games.pdf │ ├── loja_games.png │ └── loja_games.sql ├── 03_spring ├── 01.md ├── 02.md ├── 03.md ├── 04.md ├── 05.md ├── 06.md ├── 07.md ├── 08.md ├── 09.md ├── 10.md ├── 11.md ├── 12.md ├── 13.md ├── 14.md ├── 15.md ├── 16.md ├── 17.md ├── 18.md ├── 19.md ├── 20.md ├── 21.md ├── 22.md ├── 23.md ├── 24.md ├── README.md ├── guia_jpa.md ├── java_tipos.md ├── old │ ├── deploy_client.md │ └── deploy_organizacao.md └── uml.md ├── 04_fluxo_git ├── 01_fluxo_git.md ├── 02_github_organizations.md ├── 03_deploy_organizacao_render.md └── README.md ├── 05_devops ├── README.md ├── ci_cd.md ├── ci_cd_pratica.md ├── container.md ├── ddd.md ├── github_actions.md ├── orquestracao_pratica.md ├── orquestrador.md ├── solid.md ├── solid_01.md ├── solid_02.md ├── solid_03.md ├── solid_04.md ├── solid_05.md ├── tdd.md └── tdd_pratica.md └── README.md /00_ambiente/00_install_git.md: -------------------------------------------------------------------------------- 1 |

Guia de Instalação do GIT - Windows

2 | 3 | 4 | 1. Faça o Download da Instalação do Git através do endereço: **https://git-scm.com/download/win** 5 | 6 | 2. Você será redirecionado para o site do Git. Faça o download do arquivo **64-bit Git for Windows Setup** indicado na imagem abaixo: 7 | 8 |
9 | 10 | 3. Execute o arquivo **64-bit Git for Windows Setup**, com um duplo clique do mouse. 11 | 12 | 4. Na janela **Information**, será exibida a licença do Git. Clique em **Next** para continuar. 13 | 14 |
15 | 16 | 5. Na janela **Select Destination Location**, será definida a pasta onde o Git será instalado. Mantenha a pasta padrão, como mostra a imagem abaixo e clique em **Next** para continuar. 17 | 18 |
19 | 20 | 6. Na janela **Select Components**, você pode selecionar os componentes do Git que serão instalados. Mantenha as opções da instalação padrão, como mostra a imagem abaixo e clique em **Next** para continuar. 21 | 22 |
23 | 24 | 7. Na janela **Select Start Menu Folder**, você pode indicar o nome da pasta no Menu Iniciar do Windows onde os atalhos do Git serão criados. Mantenha as opções da instalação padrão, como mostra a imagem abaixo e clique em **Next** para continuar. 25 | 26 |
27 | 28 | 8. Na janela **Choosing the default editor used by Git**, você pode selecionar o Editor de Código (IDE) padrão do Git. Neste tutorial sugerimos utilizar o **Visual Studio Code** (caso esteja instalado), como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 29 | 30 |
31 | 32 | *Caso você não tenha o **Visual Studio Code** instalado na sua máquina, você pode deixar a opção padrão do instalador do Git e configurar manualmente depois de instalar o Visual Studio Code.* 33 | 34 | 9. Na janela **Adjusting the name of the initial branch in new repositories**, você pode alterar o nome padrão de um novo repositório Git. Vamos alterar marcando a opção **Override the default branch name for new repositories** e indicar a palavra **main** como nome padrão para novos repositórios Git, como mostra a imagem abaixo e clique em **Next** para continuar. 35 | 36 |
37 | 38 | 10. Na janela **Adjusting your PATH environment**, você pode indicar em quais Teminais os comandos do Git serão executados. Marque a opção **Git from the command line and also from 3rd-party software** para executar os comandos em todos os terminais disponíveis no Windows (CMD - Prompt de Comando do Windows, Power Shell, Git Bash, entre outros), como mostra a imagem abaixo e clique em **Next** para continuar. 39 | 40 |
41 | 42 | 11. Na janela **Choosing the SSH executable**, você poderá selecionar qual cliente SSH (**Secure Socket Shell**) será utilizado. Mantenha a opção padrão, como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 43 | 44 |
45 | 46 | > **SSH** é a sigla para **Secure Socket Shell, que é um dos protocolos específicos de segurança de troca de arquivos entre cliente e servidor de Internet, usando criptografia**. O objetivo do SSH é permitir que pessoas desenvolvedoras ou outros usuários realizem alterações em sites e servidores utilizando uma conexão simples e segura. 47 | 48 | 12. Na janela **Choosing HTTPS transport backend**, você poderá selecionar qual o protocolo **SSL** (**Secure Socket Layer**) será utilizado. Mantenha a opção padrão, como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 49 | 50 |
51 | 52 | 13. Na janela **Configuring the line ending conversions**, você poderá configurar como o Git irá tratar os arquivos de código. Mantenha a opção padrão, como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 53 | 54 |
55 | 56 | 14. Na janela **Configuring the terminal emulator to use with Git Bash**, você poderá selecionar como o Terminal do Git Bash será emulado no Windows. Mantenha a opção padrão, como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 57 | 58 |
59 | 60 | *Como o Bash é um interpretador de comandos do mundo Unix/Linux, ele não será executado de forma nativa no Windows, ou seja, ele será emulado.* 61 | 62 | 15. Na janela **Choose the default behavior of `git pull `**, você poderá selecionar como o comando **git pull** se comportará. Mantenha a opção padrão, como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 63 | 64 |
65 | 66 | 16. Na janela **Choose a credential helper**, você poderá selecionar como o **Git** irá gerenciar os dados do usuário. Mantenha a opção padrão, como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 67 | 68 |
69 | 70 | 17. Na janela **Choose extra options**, você poderá selecionar recursos extras do **Git**. Mantenha a opção padrão, como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 71 | 72 |
73 | 74 | 18. Na janela **Configuring experimental options**, você poderá selecionar recursos experimentais (em teste) do **Git**. Mantenha a opção padrão (todas as opções desmarcadas), como mostra a imagem abaixo e na sequência clique em **Next** para continuar. 75 | 76 |
77 | 78 | 19. Aguarde a conclusão da instalação. 79 | 80 |
81 | 82 | 20. Assim que a instalação for concluída, na janela **Completing the Git Setup Wizard**, mantenha todas as opções desmarcadas e na sequência clique no botão **Finish**. 83 | 84 |
85 | 86 | 21. Na sequência será solicitado que você se conecte com o **Github**. **Caso não seja solicitado após a instalação, ao enviar um arquivo para o Github pela primeira vez, o Git irá solicitar a autenticação**. Clique no botão **Sign in with your browser**. 87 | 88 |
89 | 90 | 22. O seu Navegador da Internet será aberto e você será redirecionado para a página **Sign in to GitHub**, semelhante a imagem abaixo: 91 | 92 |
93 | 94 | 23. Digite o seu usuário e senha do Github para autenticar. Na sequência será exibida a janela abaixo, informando que a autenticação foi realizada com sucesso! 95 | 96 |
97 | 98 |

99 | 100 |
Voltar
101 | -------------------------------------------------------------------------------- /00_ambiente/01_install_java_17.md: -------------------------------------------------------------------------------- 1 | 

Guia de Instalação do Java - Versão 17

2 | 3 |

Passo 01 - Download do instalador

4 | 5 | 1) Acesse o site: https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html para efetuar o download do **Java SE 17**. 6 | 7 |
8 | 9 | 2) Role a tela para abaixo e localize o link **Windows X64 Installer**, conforme indicado na figura abaixo: 10 | 11 |
12 | 13 | 3. Clique no link par fazer o download 14 | 4. Acesse a sua pasta de **Downloads** e localize o arquivo do Instalador do Java (JDK-17), conforme indicado na figura abaixo: 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |

ATENÇÃO: No momento em que este guia foi escrito, a versão mais atual do Java 17 era a versão 17.0.3.1. Ao utilizar este guia no futuro, pode ser que a versão mais atual do Java 17 seja outra

24 | 25 | 5. Dê um duplo clique sobre o arquivo para iniciar o instalador. 26 | 27 | 28 |

Passo 02 - Instalação e configuração

29 | 30 | 1. Na janela **Setup**, clique no botão **Next** para continuar. 31 | 32 |
33 | 34 | 2. Na janela **Destination Folder**, clique no botão **Next** para continuar. 35 | 36 |
37 | 38 | 3. Na janela **Progress**, aguarde a conclusão da instalação. Caso seja solicitada a confirmação da instalação, clique em **OK** para continuar. 39 | 40 |
41 | 42 | 4. Na janela **Complete**, clique no botão **Close** para concluir. 43 | 44 |
45 | 46 |

Passo 03 - Configuração das Variáveis de Ambiente

47 | 48 | 1. Na Caixa de pesquisas, localize o aplicativo **Editar as varáveis de ambiente do sistema** e clique no botão **Abrir** (Marcado em vermelho na imagem). 49 | 50 |
51 | 52 | 2. Na janela **Propriedades do Sistema**, clique no botão **Variáveis de Ambiente** para continuar. 53 | 54 |
55 | 56 | 3. Na janela **Variáveis de Ambiente**, no item **Variáveis do Sistema** e clique no botão **Novo...** para continuar. 57 | 58 |
59 | 60 | 4. Na janela **Nova Variável de Sistema**, preencha os campos de acordo a imagem abaixo e clique no botão **OK** para concluir. 61 | 62 |
63 | 64 | ```bash 65 | JAVA_HOME 66 | C:\Program Files\Java\jdk-17.0.3.1 67 | ``` 68 | 69 | 5. Na janela **Variáveis de Ambiente**, no item **Variáveis do Sistema**, localize e selecione a variável **Path**. Na sequência clique no botão **Editar...** 70 | 71 |
72 | 73 | 6. Na janela **Editar variável de ambiente**, clique no botão **Novo** 74 | 75 |
76 | 77 | 7. Insira a nova variável, de acordo com a figura abaixo: 78 | 79 |
80 | 81 | ```bash 82 | C:\Program Files\Java\jdk-17.0.3.1 83 | ``` 84 | 85 | 8. Para verificar se a instalação do Java 17 foi bem sucedida, execute o atalho para abrir a janela Executar. 86 | 87 |
88 | 89 | 9. Digite o comando **cmd** para abrir o **Prompt de comando do Windows**. 90 | 10. Verifique se o **Java 17** está instalado corretamente através do comando: 91 | 92 | ```bash 93 | java -version 94 | ``` 95 | 11. Se estiver tudo OK, será exibida a mensagem abaixo: 96 | 97 |
98 | 99 |

100 | 101 |
Voltar
102 | -------------------------------------------------------------------------------- /00_ambiente/02_install_sts.md: -------------------------------------------------------------------------------- 1 |  2 |

Guia de Instalação do Spring Tools Suite (STS)

3 | 4 | O Spring Tool Suite (STS) é uma IDE baseada no Eclipse, que facilita o uso de Spring de modo geral. Ela já vem com o Spring configurado e praticamente pronta para uso. 5 | 6 |

Requisitos

7 | 8 | - Java Development (JDK) Versão 17 ou superior 9 | - Winrar caso dê erro na descompactação via Java 10 | 11 |

Passo 01 - Instalação

12 | 13 | 1. Acesse o site: https://spring.io/tools 14 | 15 |
16 | 17 | 2. Faça o download do STS for Windows, conforme indicado na figura abaixo: 18 | 19 |
20 | 21 | 3. Após a conclusão do download, localize o arquivo que foi baixado (Geralmente na pasta **Downloads**) 22 | 23 |
24 | 25 | 4. Abra o arquivo: **spring-tool-suite-4-4.14.1.RELEASE-e4.23.0-win32.win32.x86_64.self-extracting.jar** 26 | 27 | | |

**ATENÇÃO:** No momento em que este guia foi escrito, a versão mais atual do STS era a versão 4.14.1. Ao utilizar este guia no futuro, pode ser que a versão mais atual seja outra*

| 28 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 29 | 30 | 5. Será perguntado com qual programa você deseja abrir o arquivo do tipo Jar. Selecione o **Java Platform(TM) SE Binary**, marque a opção **Sempre usar este aplicativo para abrir arquivos Jar** e clique em **OK** para continuar. 31 | 32 |
33 | 34 | 6. Enquanto o STS é descompactado, será exibida a imagem abaixo: 35 | 36 |
37 | 38 | 7. Caso seja exibida a mensagem abaixo, significa que você já descompactou o STS na pasta onde você fez o download. Siga para o passo 9. 39 | 40 |
41 | 42 | 8. Observe que na pasta onde você salvou o instalador do STS, será criada uma pasta com o nome: **sts-4.14.1.RELEASE** (a versão pode ser diferente) 43 | 44 | 9. Mova esta pasta para dentro de C:\Program Files\ ou C:\Arquivos de Programas\ 45 | 46 | 10. Abra a pasta e execute o arquivo: **SpringToolSuite4.exe** 47 | 48 | 11. Na próxima janela, informe a pasta onde o STS irá criar a **Workspace** (Pasta onde serão salvos os projetos Spring). 49 | 50 |
51 | 52 | 12. Mantenha a pasta padrão (C:\Users\seu usuário\Documents\workspace-spring-tool-suite-4-4.14.1.RELEASE), marque a opção **Use this as the default and do not ask again** e clique no botão **Launch** (a versão pode ser diferente). 53 | 13. A instalação está concluída! 54 | 55 | 56 | 57 | 58 | 59 | 60 |

ATENÇÃO:Não mova o arquivo SpringToolSuite4.exe da pasta do STS para a Área de Trabalho. Para criar um atalho, clique com o botão direito do mouse sobre o arquivo e clique na opção Criar atalho. Em seguida, mova o atalho para Área de Trabalho.

61 | 62 |

Erro de descompactação - item 6

63 | 64 | Caso ocorra algum erro no processo de descompactação do STS através do Java, você pode utilizar o aplicativo **Winrar** para descompactar o STS. 65 | 66 | 1. Faça o download do **Winrar** (https://www.win-rar.com/) e instale o aplicativo 67 | 68 | 3. Descompacte o arquivo: **spring-tool-suite-4-4.14.1.RELEASE-e4.23.0-win32.win32.x86_64.self-extracting.jar** (a versão pode ser diferente) clicando com o botão direito do mouse sobre o arquivo e no menu que será aberto, clique na opção **extract here**. 69 | 70 |
71 | 72 | 4. Observe que será descompactado um arquivo chamado **contents.zip**. 73 | 74 |
75 | 76 | 5. Descompacte este arquivo clicando com o botão direito do mouse sobre ele, e no menu, clique na opção **extract here**. 77 | 78 |
79 | 80 | 5. Siga as instruções do passo a passo da instalação a partir do item 8 81 | 82 |

Passo 02 - Configurando o STS para utilizar o Java 17

83 | 84 | 1. Clique no menu **Window 🡒 Preferences**. 85 | 86 |
87 | 88 | 2. Na janela Preferences, no menu do lado esquerdo, clique na opção Java 🡒 Installed JREs. 89 | 90 |
91 | 92 | 3. Na janela Installed JREs, clique botão Add... 93 | 94 |
95 | 96 | 4. Na janela Add JRE, selecione a opção **Standard VM** e clique no botão Next. 97 | 98 |
99 | 100 | 5. Na próxima tela, clique no botão Directory.... 101 | 102 |
103 | 104 | 6. Na janela Selecionar pasta, localize a pasta onde o **Java - versão 17** foi instalado (***C:\Program Files\Java\jdk-17.0.3.1***) e clique no botão Selecionar pasta. 105 | 106 |
107 | 108 | ```Bash 109 | C:\Program Files\Java\jdk-17.0.3.1 110 | ``` 111 | 112 | 113 | 114 | 115 | 116 | 117 |

ATENÇÃO: No momento em que este guia foi escrito, a versão mais atual do Java 17 era a versão 17.0.3.1. Ao utilizar este guia no futuro, pode ser que a versão mais atual do Java 17 seja outra.

118 | 119 | 7. Para finalizar, clique no botão Finish. 120 | 121 |
122 | 123 | 8. Na janela Installed JREs, deixe selecionado o Java - versão 17 que você acabou de adicionar e clique botão Apply and Close para concluir. 124 | 125 |
126 | 127 |

Passo 03 - Configurar o botão Browser

128 | 129 | Na janela Spring Boot Dashboard existe um botão chamado Open Browser , que permite carregar o projeto em execução no STS no Navegador da Internet de sua preferência. 130 | 131 |
132 | 133 | Caso a janela **Spring Boot Dashboard** não esteja visível, clique no botão **Boot Dashboard** , localizado na barra de Ferramentas do STS (abaixo do menu Search). 134 | 135 | Para configurar o seu Navegador de preferência, siga os passos abaixo: 136 | 137 | 1. Clique no menu **Window 🡒 Preferences** 138 | 139 |
140 | 141 | 2. Na janela Preferences, no menu do lado esquerdo, clique na opção General 🡒 Web Browser 142 | 143 |
144 | 145 | 3. Na janela que será aberta, marque a opção Use external web browser, escolha o Navegador de sua preferência e clique no botão Apply and Close. 146 | 147 |
148 | 149 | 150 | 151 | 152 | 153 | 154 |

ATENÇÃO: A lista de navegadores exibirá apenas os navegadores que estiverem instalados na sua máquina.

155 | 156 | 4. Após executar o seu projeto Spring, clique no Botão **Open Browser** para abrir a sua aplicação no Navegador configurado. 157 | 158 |

Resolução de Problemas - Spring no STS

159 | 160 |

Erro 01 - Ansi Console

161 | 162 | Ao executar o primeiro projeto no STS, a mensagem de erro abaixo será exibida: 163 | 164 |
165 | 166 | Esta mensagem indica que o tamanho do Buffer do console (O numero de caracteres e dados de cor para gerar uma janela de console) está pequeno. Para corrigir o problema, siga os passos abaixo: 167 | 168 | 1. Clique no menu **Window 🡒 Preferences** 169 | 170 |
171 | 172 | 2. Na janela Preferences, no menu do lado esquerdo, clique na opção Run/Debug 🡒 Console 173 | 174 |
175 | 176 | 3. Na janela que será aberta, altere a opção Console buffer size (characters) para **1000000** e clique no botão **Apply and Close** 177 | 178 |
179 | 180 |

Erro 02 - Alertas de Segurança do Windows

181 | 182 | Alerta de Segurança do Windows (janelas abaixo), informa que o STS e o JDK não tem autorização para acessar as redes públicas e privadas. Como o STS em conjunto com o JDK simulam um Servidor WEB é necessário que ambos possuam este acesso. 183 | 184 |
185 | 186 |
187 | 188 |
189 | 190 | Para corrigir o problema, marque as duas opções de acesso (**Redes Privadas e Redes Públicas**) e clique no botão **Permitir Acesso** em ambas as janelas. 191 | 192 |

193 | 194 |
Voltar
195 | -------------------------------------------------------------------------------- /00_ambiente/03_install_mysql.md: -------------------------------------------------------------------------------- 1 | 

Guia de Instalação do MySQL for Windows

2 | 3 |

Passo 01 - Download do instalador

4 | 5 | 1) Acesse o site: https://dev.mysql.com/downloads/ para efetuar o download do **MySQL Server - Community**. 6 | 7 | 2) Clique no link **MySQL installer for Windows**, conforme indicado na figura abaixo: 8 | 9 |
10 | 11 | 3) Clique no segundo link, **Windows (x86, 32-bit), MSI Installer**, conforme indicado na figura abaixo: 12 | 13 |
14 | 15 | | |

**ATENÇÃO:** No momento em que este guia foi escrito, a versão mais atual do MySQL era a versão 8.0.26.0. Ao utilizar este guia no futuro, pode ser que a versão mais atual seja outra*

| 16 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 17 | 18 | 4) Clique no link **No thanks, just start my download**, para iniciar o download imediatamente sem cadastro, conforme indicado na figura abaixo: 19 | 20 |
21 | 22 | 5) Salve o arquivo. 23 | 24 |
25 | 26 | 6) Abra a pasta de downloads e execute o instalador com um duplo clique sobre o arquivo. 27 | 28 |
29 | 30 |

Passo 02 - Instalação e configuração

31 | 32 | 1. Na janela **Choosing a Setup Type**, marque a opção **Custom** e clique no botão **Next** para continuar. 33 |
34 | 35 | 2. Na janela **Select Products**, marque a opção **MySQL Server** (última versão), como mostra a figura abaixo e clique no botão para adicionar na lista de produtos que serão instalados. 36 |
37 | 38 | 3. Ainda na janela **Select Products**, marque a opção **MySQL Workbench** (última versão), como mostra a figura abaixo e clique no botão para adicionar na lista de produtos que serão instalados. 39 |
40 | 41 | 4. Verifique se a lista de produtos que serão instalados está correta e clique no botão **Next** para continuar. 42 |
43 | 44 | 5. Na janela **Installation**, clique no botão **Execute** para iniciar a instalação. 45 |
46 | 47 | 6. Quando a instalação dos produtos for concluída, clique no botão **Next** para continuar. 48 |
49 | 50 | 7. Na janela **Product Configuration**, clique no botão **Next** para continuar. 51 |
52 | 53 | 8. Na janela **Type and Networking**, mantenha a configuração padrão clique no botão **Next** para continuar. 54 |
55 | 56 | 9. Na janela **Authentication Method**, mantenha a configuração padrão clique no botão **Next** para continuar. 57 |
58 | 59 | 10. Na janela **Accounts and Roles**, digite uma senha para o usuário **root** (Usuário Administrador do MySQL) e clique no botão **Next** para continuar. Recomendamos que você defina a senha do MySQL como **root** (Veja a observação na próxima página). 60 | 61 |
62 | 63 |

*** Importante ***

64 | 65 | Recomendamos o uso da senha **root** como senha do MySQL por se tratar de uma senha padrão, fácil de ser lembrada e que pode ser compartilhada livremente no Github. 66 | Caso você opte por outra senha, anote a senha em um lugar seguro e/ou utilize uma senha que você não se esquecerá no futuro. 67 | Outro cuidado importante é **não utilize uma senha de uso pessoal tais como e-mail, redes sociais e etc**. Lembre-se que você irá compartilhar códigos através do Github e a sua senha ficará exposta nos repositórios do Github. 68 | **Caso você esqueça a sua senha será necessário reinstalar o MySQL para cadastrar uma nova senha**. 69 | 70 | 11. Na janela **Windows Service**, mantenha a configuração padrão clique no botão **Next** para continuar. 71 |
72 | 73 | 12. Na janela **Apply Configuration**, clique no botão **Execute** para aplicar as configurações. 74 |
75 | 76 | 13. Quando a configuração for concluída, clique no botão **Next** para continuar. 77 |
78 | 79 | 14. Na janela **Product Configuration**, clique no botão **Next** para aplicar as configurações. 80 |
81 | 82 | 15. Na janela **Installation Complete**, clique no botão **Finish** para finalizar a instalação. 83 |
84 | 85 | 16. Ao finalizar a instalação o **MySQL Workbench** será inicializado. 86 |
87 | 88 |

Passo 03 - Testando a conexão no Workbench

89 | 90 | 1. No MySQL Workbench, Clique sobre a Conexão Local instance MySQL80 91 | 92 |
93 | 94 | 2. Caso seja solicitada a senha, digite a senha do usuário root e marque a opção Save password in vault para gravar a senha e não perguntar novamente. 95 | 96 |
97 | 98 | 3. Será aberta a janela principal do MySQL Workbench. Para testar o MySQL digite o comando select @@version na janela query1, como mostra a figura abaixo (marcado em azul). Em seguida, clique no ícone para executar a instrução. Será exibida a versão do MySQL que está instalada no seu computador, como mostra a figura abaixo (marcado em vermelho). 99 | 100 |
101 | 102 |

Erro: Workbench desconectado

103 | 104 | Caso a Barra de Ferramentas do Editor de Consultas esteja desabilitada, como mostra a figura abaixo, significa que você não efetuou a conexão com o MySQL Server na tela inicial do MySQL Workbench. 105 | 106 |
107 | 108 | Observe que na Guia do Editor de consultas aparece a palavra **unconnected** (desconectado), como mostra a figura abaixo: 109 | 110 |
111 | 112 | Para Corrigir este problema, clique no ícone , ao lado da guia do Editor de consultas para retornar para a tela inicial do Workbench. 113 | 114 |
115 | 116 | Na tela inicial, dê um duplo clique sobre a conexão **Local instance MySQL80** (Conexão local), como mostra a figura abaixo, para efetuar a conexão com o MySQL Server. 117 | 118 |
119 | 120 | Caso seja solicitada a senha do usuário root, como mostra a figura abaixo, digite a senha e marque a opção: **Save password in vault**, para gravar a senha e não solicitar novamente. 121 | 122 |
123 | 124 | Observe que após efetuar a conexão com o MySQL Server, a Barra de Ferramentas estará ativada, a palavra **unconnected** será substituída por **Local instance MySQL80** na Guia do Editor de consultas e o MySQL voltará a funcionar normalmente. 125 | 126 |
127 | 128 |

Desabilitar o Update diário à 0h

129 | 130 | O MySQL configura durante a instalação a atualização diária à 0h. Todos os dias neste horário, aparece uma janela do **Prompt de Comando do Windows** executando uma série de comandos e ao finalizar fecha a janela automaticamente. Para desabilitar esta opção, siga os passos abaixo: 131 | 132 | 1. Na Caixa de pesquisas, localize o Agendador de Tarefas (Marcado em vermelho na imagem), e clique no Agendador de Tarefas (Marcado em azul na imagem). 133 | 134 |
135 | 136 | 2. Na janela do Agendador de Tarefas, Localize a pasta do MySQL como mostra a figura abaixo: 137 | 138 |
139 | 140 | 3. Clique sobre a tarefa ManifestUpdate com o botão direito mouse e clique na opção Excluir ou Desativar. 141 | 142 |
143 | 144 |

145 | 146 |
Voltar
147 | -------------------------------------------------------------------------------- /00_ambiente/04_uninstall_mysql.md: -------------------------------------------------------------------------------- 1 | 

Guia de Reinstalação do MySQL Server for Windows

2 | 3 |

Passo 01 - Desinstalação do MySQL Server

4 | 5 | 1. Na Caixa de pesquisas, localize o MySQL (Marcado em vermelho na imagem), e clique no MySQL Installer - Community (Marcado em azul na imagem). 6 | 7 |
8 | 9 | 2. Na janela MySQL Installer, clique no botão Remove . 10 | 11 |
12 | 13 | 3. Na janela Select Products to Remove, marque a opção **MySQL server** e clique no botão Next . 14 | 15 |
16 | 17 | 4. Na janela Remove Server, marque a opção **remove the data directory** e clique no botão Next . 18 | 19 |
20 | 21 | 5. Na janela Remove Selected Products, clique no botão Execute . 22 | 23 |
24 | 25 | 6. Ao concluir a desinstalação do MySQL Server, clique no botão Finish . 26 | 27 |
28 | 29 | 7. Será aberta a janela MySQL Installer. Observe que o MySQL Server foi desinstalado e já não aparece mais na lista de produtos instalados. 30 | 31 |
32 | 33 |

Passo 02 - Reinstalação e configuração

34 | 35 | 1. Na janela MySQL Installer, clique no botão Add . 36 | 37 |
38 | 39 | 2. Na janela Select Products, marque a opção MySQL Server (última versão), como mostra a figura abaixo e clique no botão para adicionar na lista de produtos que serão instalados. 40 | 41 |
42 | 43 | 3. Verifique se o MySQL Server foi adicionado na lista e clique no botão Next para continuar. 44 | 45 |
46 | 47 | 4. Na janela Installation ou Download, clique no botão Execute para iniciar a instalação e/ou download do MySQL Server. 48 | 49 |
50 | 51 | 5. Caso o instalador tenha feito o download de uma nova versão do MySQL, a janela Download indicará o final do download. Clique no botão Next para iniciar a instalação do MySQL Server. 52 | 53 |
54 | 55 | 6. Na janela Installation, clique no botão Execute para iniciar a instalação. 56 | 57 |
58 | 59 | 7. Quando a instalação dos produtos for concluída, clique no botão Next para continuar. 60 | 61 |
62 | 63 | 8. Na janela Product Configuration, clique no botão Next para continuar. 64 | 65 |
66 | 67 | 9. Na janela Type and Networking, mantenha a configuração padrão clique no botão Next para continuar. 68 | 69 |
70 | 71 | 10. Na janela **Authentication Method**, mantenha a configuração padrão clique no botão Next para continuar. 72 | 73 |
74 | 75 | 11. Na janela Accounts and Roles, digite uma senha para o usuário root (Usuário Administrador do MySQL) e clique no botão Next para continuar. Recomendamos que você defina a senha do MySQL como root (Veja a observação na próxima página). 76 | 77 |
78 | 79 |

*** Importante ***

80 | 81 | Recomendamos o uso da senha **root** como senha do MySQL por se tratar de uma senha padrão, fácil de ser lembrada e que pode ser compartilhada livremente no Github. 82 | Caso você opte por outra senha, anote a senha em um lugar seguro e/ou utilize uma senha que você não se esquecerá no futuro. 83 | Outro cuidado importante é **não utilize uma senha de uso pessoal tais como e-mail, redes sociais e etc**. Lembre-se que você irá compartilhar códigos através do Github e a sua senha ficará exposta nos repositórios do Github. 84 | **Caso você esqueça a sua senha será necessário reinstalar o MySQL para cadastrar uma nova senha**. 85 | 86 | 12. Na janela Windows Service, mantenha a configuração padrão clique no botão Next para continuar. 87 | 88 |
89 | 90 | 13. Na janela **Apply Configuration**, clique no botão **Execute** para aplicar as configurações. 91 | 92 |
93 | 94 | 14. Quando a configuração for concluída, clique no botão Next para continuar. 95 | 96 |
97 | 98 | 15. Na janela **Product Configuration**, clique no botão Next para aplicar as configurações. 99 | 100 |
101 | 102 | 16. Na janela Installation Complete, clique no botão Finish para finalizar a instalação. 103 | 104 |
105 | 106 | 17. Ao finalizar a instalação, o instalador retornará para a janela **MySQL Installer**. Feche a janela para concluir. 107 | 108 |
109 | 110 |

Passo 03 - Testando a conexão no Workbench

111 | 112 | 1. Na Caixa de pesquisas, localize o MySQL (Marcado em vermelho na imagem), e clique no MySQL Workbench (Marcado em azul na imagem). 113 | 114 |
115 | 116 | 2. No MySQL Workbench, Clique sobre a Conexão Local instance MySQL80 117 | 118 |
119 | 120 | 3. Caso seja solicitada a senha, digite a senha do usuário root e marque a opção Save password in vault para gravar a senha e não perguntar novamente. 121 | 122 |
123 | Não esqueça de anotar a senha para não esquecer 124 | 125 | 4. Será aberta a janela principal do MySQL Workbench. Para testar o MySQL digite o comando select @@version na janela query1, como mostra a figura abaixo (marcado em azul). Em seguida, clique no ícone para executar a instrução. Será exibida a versão do MySQL que está instalada no seu computador, como mostra a figura abaixo (marcado em vermelho). 126 | 127 |
128 | 129 |

130 | 131 |
Voltar
132 | -------------------------------------------------------------------------------- /00_ambiente/05_install_Insomnia.md: -------------------------------------------------------------------------------- 1 | 

Guia de Instalação do Insomnia

2 | 3 | 1. Acesse o site do node: **[https://insomnia.rest/download](https://insomnia.rest/download)** e clique no botão **Download Insomnia for Windows**. 4 |
5 | 6 | 2. Após efetuar o download, execute o instalador do Insomnia. 7 | 8 | 3. Ao abrir o instalador, será exibida a imagem abaixo. Ao concluir a instalação, a imagem será fechada e o programa será inicializado. 9 | 10 |
11 | 12 | 4. Na janela **Welcome to Insomnia**, clique no link **Don't share usage analytics** para continuar. 13 | 14 |
15 | 16 | 5. Ainda na janela **Welcome to Insomnia**, clique no link **Skip** para continuar. 17 | 18 |
19 | 20 | 6. Ao concluir as etapas anteriores, a janela principal do Insomnia será aberta e a instalação estará concluída. 21 | 22 |
23 | 24 |

25 | 26 |
Voltar
27 | -------------------------------------------------------------------------------- /00_ambiente/06_install_vscode.md: -------------------------------------------------------------------------------- 1 | 

Guia de Instalação do Visual Studio Code - VSCode

2 | 3 | 1. Acesse o link: https://code.visualstudio.com/download para efetuar o download do VSCode. 4 |
5 | 6 | 2. Marque a opção **Eu aceito o acordo** e clique no botão **Próximo** para continuar. 7 |
8 | 9 | 3. Clique no botão **Próximo** para continuar. 10 |
11 | 12 | 4. Clique no botão **Próximo** para continuar. 13 |
14 | 15 | 5. Marque todas as opções e clique no botão **Próximo** para continuar. 16 |
17 | 18 | 6. Clique no botão **Instalar** para continuar. 19 |
20 | 21 | 7. Clique no botão **Concluir** para finalizar a instalação. 22 |
23 | 24 | 8. O **VSCode** está pronto para uso. 25 |
26 | 27 |

28 | 29 |
Voltar
30 | -------------------------------------------------------------------------------- /00_ambiente/07_install_node.md: -------------------------------------------------------------------------------- 1 | 

Guia de Instalação do Node

2 | 3 | 1. Acesse o site do node: **https://nodejs.org/en/** e clique no link para efetuar o download da versão **LTS** . 4 | 5 |
6 | 7 | | |

**ATENÇÃO:** No momento em que este guia foi escrito, a versão LTS mais atual do Node era a versão 16.15.0 LTS. Ao utilizar este guia no futuro, pode ser que a versão mais atual seja outra*

| 8 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 9 | 10 | 2. Após efetuar o download, execute o instalador do Node. 11 | 12 | 3. Ao abrir o instalador, caso seja exibida a mensagem abaixo, clique em **OK** para continuar. 13 | 14 |
15 | 16 | 4. Na janela **Welcome to Node.js Setup Wizard**, clique no botão **Next** para continuar. 17 | 18 |
19 | 20 | 5. Na janela **End-User License Agreement**, marque a opção **I accept the terms in the License Agreement** e clique no botão **Next** para continuar. 21 | 22 |
23 | 24 | 6. Na janela **Destination Folder**, clique no botão **Next** para continuar. 25 | 26 |
27 | 28 | 7. Na janela **Custom Setup**, clique no botão **Next** para continuar. 29 | 30 |
31 | 32 | 8. Na janela **Tools for Native Modules**, clique no botão **Next** para continuar. 33 | 34 |
35 | 36 | 9. Na janela **Ready to install Node.js**, clique no botão **Install** para continuar. 37 | 38 |
39 | 40 | 10. Aguarde a conclusão da Instalação. Caso seja solicitada a confirmação da instalação, clique no botão **OK** para continuar. 41 | 42 |
43 | 44 | 11. Na janela **Completed the Node.js Setup Wizard**, clique no botão **Finish** para concluir. 45 | 46 |
47 | 48 | 12. Para verificar se a instalação do Node foi bem sucedida, execute o atalho para abrir a janela Executar. 49 | 50 |
51 | 52 | 13. Digite o comando **cmd** para abrir o **Prompt de comando do Windows**. 53 | 54 | 14. Verifique se o **Node** está instalado através do comando: 55 | 56 | ```bash 57 | node -v 58 | ``` 59 |
60 | 61 | 15. Verifique também se o **NPM** está instalado através do comando: 62 | 63 | ```bash 64 | npm -v 65 | ``` 66 | 67 |
68 | 69 |

70 | 71 |
Voltar
72 | -------------------------------------------------------------------------------- /00_ambiente/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Bootcamp - Java Full Stack

5 | 6 |

Preparação do Ambiente

7 | 8 | 0. Guia de Instalação - Git 9 | 1. Guia de Instalação - Java 17 10 | 2. Guia de Instalação - STS 11 | 3. Guia de Instalação - MySQL 12 | 4. Guia de Reinstalação - MySQL (Esqueceu a senha do MySQL) 13 | 5. Guia de Instalação - Insomnia 14 | 6. Guia de Instalação - VSCode 15 | 7. Guia de Instalação - Node 16 | 17 |

18 | 19 |
20 |
Home
21 | -------------------------------------------------------------------------------- /02_mysql/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Bootcamp - Java Full Stack

5 | 6 |

Banco de Dados - MySQL

7 | 8 | 1. Introdução a Banco de Dados com MySQL 9 | 2. Banco de Dados com MySQL - parte 01 10 | 3. Banco de Dados com MySQL - parte 02 11 | 4. Diagrama Entidade Relacionamento (DER) no MySQL Workbench 12 | 13 |

14 | 15 |
16 |
Home
17 | -------------------------------------------------------------------------------- /02_mysql/der/loja_games.mwb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafaelq80/spring_content/95489d9e92b02e44c67045b5c7354fe3efa6155f/02_mysql/der/loja_games.mwb -------------------------------------------------------------------------------- /02_mysql/der/loja_games.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafaelq80/spring_content/95489d9e92b02e44c67045b5c7354fe3efa6155f/02_mysql/der/loja_games.pdf -------------------------------------------------------------------------------- /02_mysql/der/loja_games.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafaelq80/spring_content/95489d9e92b02e44c67045b5c7354fe3efa6155f/02_mysql/der/loja_games.png -------------------------------------------------------------------------------- /02_mysql/der/loja_games.sql: -------------------------------------------------------------------------------- 1 | -- Cria o Banco de dados 2 | CREATE DATABASE db_games; 3 | 4 | -- Seleciona o Banco de dados para uso 5 | USE db_games; 6 | 7 | -- Cria a tabela Categorias 8 | CREATE TABLE tb_categorias ( 9 | id BIGINT NOT NULL AUTO_INCREMENT, 10 | tipo VARCHAR(255) NOT NULL, 11 | PRIMARY KEY (id) 12 | ); 13 | 14 | -- Insere dados na tabela Categorias 15 | INSERT INTO tb_categorias (tipo) VALUES ("E-Sports"); 16 | INSERT INTO tb_categorias (tipo) VALUES ("Ação"); 17 | INSERT INTO tb_categorias (tipo) VALUES ("Aventura"); 18 | INSERT INTO tb_categorias (tipo) VALUES ("Estratégia"); 19 | INSERT INTO tb_categorias (tipo) VALUES ("RPG"); 20 | INSERT INTO tb_categorias (tipo) VALUES ("Simulação"); 21 | INSERT INTO tb_categorias (tipo) VALUES ("Outros"); 22 | 23 | -- Lista todas as Categorias 24 | Select * from tb_categorias; 25 | 26 | -- Cria a tabela Usuários 27 | CREATE TABLE tb_usuarios ( 28 | id BIGINT NOT NULL AUTO_INCREMENT, 29 | usuario VARCHAR(255) NOT NULL, 30 | nome VARCHAR(255) NOT NULL, 31 | senha VARCHAR(255) NOT NULL, 32 | foto VARCHAR(255), 33 | data_nascimento DATE NOT NULL, 34 | PRIMARY KEY (`id`) 35 | ); 36 | 37 | -- Insere dados na tabela Usuários 38 | insert into tb_usuarios(usuario, nome, senha, foto, data_nascimento) values ("admin@email.com.br", "Administrador", "123a456*78", "https://i.imgur.com/FETvs2O.jpg", "2001-11-22"); 39 | insert into tb_usuarios(usuario, nome, senha, foto, data_nascimento) values ("mariana@email.com.br", "Mariana Maria da Silva", "123@456&78", "https://i.imgur.com/mB3VM2N.jpg", "2001-11-22"); 40 | insert into tb_usuarios(usuario, nome, senha, foto, data_nascimento) values ("adriana@email.com.br", "Adriana Kaylany de Souza", "123l456t78", "https://i.imgur.com/5M2p5Wb.jpg", "2002-12-26"); 41 | insert into tb_usuarios(usuario, nome, senha, foto, data_nascimento) values ("quico@email.com.br", "Frederico Santos", "123b456#78", "https://i.imgur.com/Sk5SjWE.jpg", "2003-12-26"); 42 | insert into tb_usuarios(usuario, nome, senha, foto, data_nascimento) values ("florinda@email.com.br", "Florinda Mezza", "123!456?78", "https://i.imgur.com/NtyGneo.jpg", "2002-12-26"); 43 | insert into tb_usuarios(usuario, nome, senha, foto, data_nascimento) values ("evelise@email.com.br", "Evelise Franco", "123f456v78", "https://i.imgur.com/EcJG8kB.jpg", "2001-12-26"); 44 | insert into tb_usuarios(usuario, nome, senha, foto, data_nascimento) values ("julmiara@email.com.br", "Julmiara Correa", "123@!456g78", "https://i.imgur.com/T12NIp9.jpg", "2000-12-26"); 45 | 46 | -- Lista todos os Usuários 47 | Select * from tb_usuarios; 48 | 49 | -- Cria a tabela Produtos 50 | CREATE TABLE tb_produtos ( 51 | id BIGINT NOT NULL AUTO_INCREMENT, 52 | nome VARCHAR(255) NOT NULL, 53 | descricao VARCHAR(500), 54 | console VARCHAR(255) NOT NULL, 55 | quantidade INT, 56 | preco DECIMAL(19,2) NOT NULL, 57 | foto VARCHAR(255), 58 | categoria_id BIGINT, 59 | usuario_id BIGINT, 60 | PRIMARY KEY (id), 61 | FOREIGN KEY (usuario_id) REFERENCES tb_usuarios (id), 62 | FOREIGN KEY (categoria_id) REFERENCES tb_categorias (id) 63 | ); 64 | 65 | -- Insere dados na tabela Produtos 66 | INSERT INTO tb_produtos (nome, descricao, console, quantidade, preco, foto, categoria_id, usuario_id) 67 | VALUES ("Kena: Bridge of Spirits", "Kena: Bridge of Spirits é o projeto de estreia da Ember Lab e impressiona ainda mais a cada replay do trailer. O estilo único de arte mistura elementos marcantes da Pixar e do Studio Ghibli, resultando em uma incrível animação.", "PS5", 50, 500.00, "https://i.imgur.com/YqasKzX.jpg", 3, 2); 68 | 69 | INSERT INTO tb_produtos (nome, descricao, console, quantidade, preco, foto, categoria_id, usuario_id) 70 | VALUES ("Returnal", "um shooter com uma pegada um pouco diferente do habitual. A visão da câmera um pouco mais próxima da protagonista promete uma experiência singular com narrativa assustadora", "PS5", 10, 400.00, "https://i.imgur.com/Xd9vF7t.jpg", 6, 3); 71 | 72 | INSERT INTO tb_produtos (nome, descricao, console, quantidade, preco, foto, categoria_id, usuario_id) 73 | VALUES ("Resident Evil Village", "Novo game da franquia de zumbis da Capcom e promete dar uma continuação majestosa ao legado do survival horror. Mais uma vez estaremos no controle de Ethan Winters e devemos escapar com vida de um misterioso vilarejo do interior europeu.", "PS5", 20, 800.00, "https://i.imgur.com/iQMTaVC.jpg", 3, 4); 74 | 75 | INSERT INTO tb_produtos (nome, descricao, console, quantidade, preco, foto, categoria_id, usuario_id) 76 | VALUES ("God of War Ragnarok", "God of War Ragnarok promete dar continuidade à história de Kratos e Atreus. O Deus da Guerra se encaixou muito bem nos moldes da mitologia nórdica e conquistou até o GoTY em 2018 — em disputa acirrada contra Red Dead Redemption 2.", "PS5", 100, 700.00, "https://i.imgur.com/8qnAKwO.jpg", 3, 5); 77 | 78 | INSERT INTO tb_produtos (nome, descricao, console, quantidade, preco, foto, categoria_id) 79 | VALUES ("Halo Infinite", "O jogo colocará os jogadores de volta na sagrada armadura espartana de Master Chief, enquanto ele combate os Banidos, uma nova ameaça à humanidade, e promete mais liberdade do que qualquer jogo recente da série, com níveis enormes.", "XBOX", 80, 1000.00, "https://i.imgur.com/ZnDckc2.jpg", 3); 80 | 81 | INSERT INTO tb_produtos (nome, descricao, console, quantidade, preco, foto) 82 | VALUES ("Flight Simulator", "O Flight Simulator promete aos jogadores a liberdade de criar seus próprios planos de vôo e decolar em qualquer lugar do mundo, voando dia e noite em condições climáticas realistas.", "XBOX", 15, 250.00, "https://i.imgur.com/cYl5vhh.jpg"); 83 | 84 | -- Lista todos os Produtos 85 | Select * from tb_produtos; 86 | 87 | -- Lista todos os Produtos com a categoria 88 | select tb_produtos.nome, tb_categorias.tipo 89 | from tb_produtos inner join tb_categorias 90 | on tb_categorias.id = tb_produtos.categoria_id; 91 | 92 | -- Lista todos os Produtos com o nome do vendedor 93 | select tb_produtos.nome, tb_usuarios.nome as vendedor 94 | from tb_produtos inner join tb_usuarios 95 | on tb_usuarios.id = tb_produtos.usuario_id; 96 | 97 | -- Lista todos os Produtos com a categoria e o vendedor 98 | select tb_produtos.nome, 99 | CONCAT('R$ ',FORMAT(tb_produtos.preco, 2,'pt_BR')) as preço, 100 | tb_categorias.tipo, 101 | tb_usuarios.nome as vendedor 102 | from tb_produtos 103 | inner join tb_categorias on tb_categorias.id = tb_produtos.categoria_id 104 | inner join tb_usuarios on tb_usuarios.id = tb_produtos.usuario_id; 105 | -------------------------------------------------------------------------------- /03_spring/03.md: -------------------------------------------------------------------------------- 1 | 

Introdução ao JPA

2 | 3 | Vamos conhecer o JPA, parte integrante do Ecossistema Spring, responsável por criar e manipular o Banco de dados da aplicação. 4 | 5 |

1. O que é JPA?

6 | 7 | JPA (ou *Java Persistence API*) é uma especificação que descreve como deve ser o comportamento dos frameworks de persistência Java que desejarem implementá-la, ou seja, não possui código que possa ser executado. 8 | 9 | No Spring, o JPA é uma biblioteca que persiste e recupera objetos que são armazenados em um Bancos de dados. Ele é responsável por fazer todas as instruções SQL sem que precisemos escrever uma única linha em nosso código SQL. 10 | 11 | A Biblioteca JPA é uma Interface que possui alguns Métodos assinados, que são os Métodos padrão da Interface (findAll, find ById, Save, deleteById e etc). Como toda e qualquer Interface, para utilizar os Métodos é necessário implementá-los dentro de uma Classe. No contexto Spring, nas Classes das Camadas Controller e Service. 12 | 13 | Apesar de ser uma Interface e não possuir nenhum Método Implementado, a especificação possui ainda algumas Classes, Interfaces e Anotações que ajudam o desenvolvedor a criar instruções SQL. Para persistir os dados com JPA, é preciso escolher uma implementação que é quem, de fato, vai fazer todo o trabalho, de acordo com o tipo de Banco de dados que será utilizado (Relacional ou Não Relacional). 14 | 15 |

1.1 Mapeamento Objeto Relacional

16 | 17 | **Mapeamento Objeto Relacional** é a representação de uma Tabela de um Banco de dados Relacional (MySQL, PostgreSQL, Oracle, SQL Server e etc), através de Classes Java, que dentro do contexto Spring e seguindo o Modelo MVC, são implementadas na Camada Model. Essa técnica de mapeamento também é conhecida como **ORM** ou *Object Relational Mapping*. 18 | 19 | Na prática, o Mapeamento cria a Relação de equivalência abaixo: 20 | 21 | | Banco de dados | | Linguagem Orientada a Objetos | 22 | | -------------- | ----- | ----------------------------- | 23 | | Tabela | **🡪** | Classe | 24 | | Coluna | **🡪** | Atributo | 25 | | Registro | **🡪** | Objeto | 26 | 27 | Enquanto que no banco de dados temos Tabelas, Colunas e Registros, em uma linguagem Orientada a Objetos, como o Java, temos o equivalente com Classes, Atributos e Objetos. Além dessa equivalência, o JPA utiliza algumas anotações que adicionarão metadados (Chave Primária, Nome da Tabela, Auto Incremento e etc), às Classes e permitirão os frameworks ORM, como o Hibernate, entrarem em ação na geração das tabelas dentro do nosso Banco de dados. 28 | 29 |

1.2. Hibernate

30 | 31 | O **Hibernate** é um framework para o mapeamento objeto-relacional escrito na linguagem Java, cujo objetivo é diminuir a complexidade entre os programas Java, baseado no modelo Orientado a Objetos, que precisam trabalhar com um banco de dados do modelo Relacional (presente na maioria dos SGBD's). Em especial, no desenvolvimento de consultas e atualizações dos dados. 32 | 33 |
34 | 35 |
36 | 37 |
Site Oficial: Hibernate 38 | 39 |
40 | 41 |

1.3. Por quê utilizar JPA?

42 | 43 | Escrever SQL para consultas, inserções e atualizações, por mais que não seja complexo, é uma tarefa repetitiva e chata. 44 | 45 | A primeira vantagem é que o JPA trás códigos SQL para consultas, inserções e atualizações básicas prontas. 46 | 47 | A segunda vantagem é que para criarmos consultas personalizadas podemos utilizar as **Query Methods**, que a partir da combinação de palavras chave, que substituem as instruções SQL, podemos criar consultas de forma rápida. 48 | 49 | A terceira vantagem é a simplificação do código-fonte da aplicação. Como muita coisa é automatizada, bem menos código é escrito para as mesmas funções. 50 | 51 |
52 | 53 |
Site Oficial: Spring Data JPA 54 | 55 |

56 | 57 |
Voltar
58 | -------------------------------------------------------------------------------- /03_spring/06.md: -------------------------------------------------------------------------------- 1 |  2 |

Projeto 02 - Blog Pessoal - Interface Postagem Repository

3 | 4 | O que veremos por aqui: 5 | 6 | 1. Criar a Interface PostagemRepository 7 | 8 |

1. O Recurso Postagem

9 | 10 | Na etapa anterior, começamos a construir o Recurso Postagem, a partir da Classe Model Postagem, onde implementamos todos os Atributos do recurso. Veja o Diagrama de Classes abaixo: 11 | 12 |
13 | 14 | Nesta etapa, vamos construir a **Interface PostagemRepository**, que irá nos auxiliar na interação com o Banco de dados. Esta Interface contém diversos Métodos pré-implementados para a manipulação dos dados de uma entidade, como Métodos para salvar, deletar, listar e recuperar dados dos objetos persistidos, além de criar consultas personalizadas chamadas **Query Methods**, que veremos mais a frente. Para utilizar todos os Métodos da Interface Repository, vamos criar dentro da Interface PostagemRepository uma **Herança** (Extends) com a Interface **JpaRepository**. Os Métodos descritos no Diagrama de Classes serão implementados na próxima etapa, na Classe **PostagemController**. 15 | 16 | O Diagrama de Classes da nossa Interface será igual a imagem abaixo: 17 | 18 |
19 | 20 |

👣 Passo 01 - Criar o Pacote Repository

21 | 22 | Na Source Folder Principal (**src/main/java**), observe que já foi criado o pacote Principal da nossa aplicação (**com.generation.blogpessoal**) e o pacote Model (**com.generation.blogpessoal.model**). Na figura abaixo, podemos visualizar os 2 pacotes: 23 | 24 |
25 | 26 | Nesta etapa, vamos criar a **Camada Repository**: 27 | 28 | 1. No lado esquerdo superior, na Guia **Package explorer**, clique com o botão direito do mouse sobre a Package **com.generation.blogpessoal**, na Source Folder **src/main/java** e clique na opção **New 🡪 Package**. 29 | 30 |
31 | 32 | 2. Na janela **New Java Package**, no item **Name**, acrescente no final do nome da Package **.repository**, como mostra a figura abaixo: 33 | 34 |
35 | 36 | 3. Clique no botão **Finish** para concluir. 37 | 38 | Quando você terminar de criar a **Camada Repository**, a sua estrutura de pacotes ficará igual a figura abaixo: 39 | 40 |
41 | 42 |

👣 Passo 02 - Criar a Interface PostagemRepository na Camada Repository

43 | 44 | Agora vamos criar a Interface Repository que chamaremos de **PostagemRepository**. 45 | 46 | 1. Clique com o botão direito do mouse sobre o **Pacote Repository** (**com.generation.blogpessoal.repository**), na Source Folder Principal (**src/main/java**), como mostra a figura abaixo: 47 | 2. Na sequência, clique na opção **New 🡪 Interface** 48 | 49 |
50 | 51 | 3. Na janela **New Java Interface**, no item **Name**, digite o nome da Interface (**PostagemRespository**), como mostra a figura abaixo: 52 | 53 |
54 | 55 | 4. Clique no botão **Finish** para concluir. 56 | 57 | Agora vamos criar o código da **Interface Repository PostagemRepository**, como mostra a figura abaixo: 58 | 59 |
60 | 61 | Vamos analisar o código: 62 | 63 | Antes de continuar, vamos relembrar **o que é uma Interface?** 64 | 65 | Uma **interface em Java** é uma **Classe Abstrata** (uma Classe que serve de modelo para outras Classes), composta somente por Métodos abstratos. E como tal, obviamente não pode ser instanciada, ou seja, ela só contém as declarações dos Métodos e constantes, nenhuma implementação, apenas as assinaturas dos Métodos, que serão implementados em uma Classe. 66 | 67 | **Linha 08:** A Anotação (Annotation) **@Repository** indica que a Interface é do tipo repositório, ou seja, ela é responsável pela interação com o Banco de dados através dos Métodos padrão (**Herdados da Interface JPA Repository**) e das **Query Methods**, que são Métodos personalizados que geram consultas (Instruções SQL do tipo Select), através da combinação de palavras chave, que representam os comandos da linguagem SQL. 68 | 69 | **Linha 09:** Observe que na declaração da Interface foi adicionada a Herança através da palavra reservada **extends** com a Interface JpaRepository, que recebe 2 parâmetros: 70 | 71 | 1. A **Classe Postagem**, que é a Entidade que será mapeada em nosso Banco de dados (Lembre-se que a Classe Postagem foi quem gerou a nossa tabela tb_postagens) 72 | 2. O **Long** representa a nossa Chave Primária (Primary Key), que é o Atributo que recebeu a anotação **@Id** na nossa Classe Postagem (o Atributo também se chama id em nossa Classe Postagem). 73 | 74 | Estes 2 parâmetros são do tipo **Java Generics** (podem receber qualquer tipo de Objeto ). Dentro contexto do JPA são o mínimo necessário para executar os Métodos padrão da Interface Repository, que serão implementados na próxima etapa na Classe **PostagemController**. Estes Métodos básicos já ficam automaticamente disponíveis no Recurso Postagem a partir do momento que a Interface PostagemRepository herda a Interface JpaRepository. 75 | 76 |
Documentação: @Repository 77 | 78 |
Documentação: Java Interface 79 | 80 |
Documentação: Classes Abstratas 81 | 82 |
Documentação: Java Generics 83 | 84 |
85 | 86 |
Código fonte da Interface Postagem Repository 87 | 88 |
89 | 90 |

Métodos Padrão da Interface JpaRepository

91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
save(Objeto objeto)Cria ou Atualiza um objeto no Banco de Dados.
findById(Long id)Retorna (exibe) um Objeto persistido de acordo com o id informado.
existsById(Long id)Retorna True se um Objeto identificado pelo id estiver persistido no Banco de dados.
findAll()Retorna (exibe) todos os Objetos persistidos.
deleteById(Long id)Localiza um Objeto persistido pelo id e deleta caso ele seja encontrado. Não é possível desfazer esta operação.
deleteAll()Deleta todos os Objetos persistidos.Não é possível desfazer esta operação.
118 | 119 |
Documentação: Métodos Padrão 120 | 121 |
122 | 123 |
Código fonte do Projeto 124 | 125 |

126 | 127 | 128 | -------------------------------------------------------------------------------- /03_spring/08.md: -------------------------------------------------------------------------------- 1 |

Projeto 02 - Blog Pessoal - Classe PostagemController - Método Consultar Postagens por Id

2 | 3 | O que veremos por aqui: 4 | 5 | 1. Criar o Método getById(Long id) para listar uma Postagem específica 6 | 7 |

1. O Recurso Postagem

8 | 9 | Na etapa anterior, começamos a construir a Classe **PostagemController** e implementamos o Método **getAll()**, que retorna todos os Objetos da Classe Postagem persistidos no Banco de dados. Vamos continuar a construção da nossa Classe Controladora implementando o **Método getById( Long id )**. 10 | 11 |
12 | 13 |

👣 Passo 01 - Criar o Método getById(Long id)

14 | 15 | Vamos implementar o Método **getById(Long id)** na Classe Postagem Controller, que retornará um Objeto específico persistido no Banco de dados, identificado pelo **id** (Identificador único do Objeto). Traçando um paralelo com o MySQL, seria o equivalente a instrução: SELECT * FROM tb_postagens where id = id;. 16 | 17 |
18 | 19 | Para processar o Método findById(Long id), vamos utilizar dois recursos da Linguagem Java, que tornam o código mais limpo e assertivo. São os recursos **Optional e Expressões Lambda**. 20 | 21 | **Optional (map):** É um contêiner para um valor que pode estar ausente. Em nosso contexto, tem como principal função evitar o erro do tipo **NullPointerException** (Objeto nulo), caso o Objeto Postagem procurado pelo Método findById(id) não seja encontrado. O retorno do Método NÃO pode ser nulo, por isso fazemos uso do Optional para que ele faça o encapsulamento e informe se o Objeto está presente ou não. 22 | 23 | **Expressões Lambda**: Representam uma função anônima, ou seja, uma função lambda é uma função sem declaração, ou seja, não é necessário colocar um nome, um tipo de retorno e modificador de acesso. A ideia é que o Método seja declarado no mesmo lugar em que será usado e a sua declaração seja implícita. As expressões lambda em Java tem a sintaxe definida como: (argumento) 🡪 (corpo). A Linguagem **Javascript/Typescript** possuem um recurso semelhante, que são as **Arrow Functions**. 24 | 25 | **Linha 30:** A anotação **@GetMapping("/{id}")** mapeia todas as Requisições **HTTP GET**, enviadas para um endereço específico (**Endpoint**), dentro do Recurso Postagem, para um Método específico que responderá as requisições, ou seja, ele indica que o Método **getById( Long id )**, responderá a todas as requisições do tipo **HTTP GET**, enviadas no endereço **http://localhost:8080/postagens/id**, onde **id** é uma **Variável de Caminho** (Path Variable), que receberá o id da Postagem que será Consultada. 26 | 27 | | |
**ATENÇÃO:** *O Endereço deste Endpoint será composto pelo Endereço do Recurso (@RequestMapping) + a variável de caminho indicada na anotação @GetMapping. Lembre-se que não pode existir dois ou mais Métodos do tipo GET com o mesmo endereço.*
| 28 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 29 | 30 | **Linha 31:** O Método **getById(@PathVariable Long id)** será do tipo **ResponseEntity** porque ele responderá Requisições HTTP (HTTP Request), com uma **Resposta HTTP** (HTTP Response). Observe que o Método possui um parâmetro do tipo **Long**, chamado **id**. 31 | 32 | **@PathVariable Long id:** Esta anotação insere o valor enviado no endereço do endpoint, na Variável de Caminho **{id}**, no parâmetro do Método **getById( Long id )**; 33 | 34 | **Exemplo:** 35 | 36 | http://localhost:8080/postagens/1 37 | 38 | Neste exemplo, o parâmetro **Long id**, do Método getById( Long id ), receberá o valor 1 (Id que será procurado em tb_postagens) 39 | 40 | | |
**ATENÇÃO:** *Por questões de boas práticas e legibilidade do código, a Variável de Caminho e o Parâmetro do Método getById devem possuir o mesmo nome.*
| 41 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 42 | 43 | : O Método além de retornar um objeto da **Classe ResponseEntity** (OK🡪200), no parâmetro Body (Corpo da Resposta), será retornado **Um Objeto da Classe Postagem**, apenas e somente se o Objeto procurado for encontrado no Banco de dados, na tabela **tb_postagens**. Observe que nesta linha também foi utilizado o recurso **Java Generics** para simplificar o retorno do Objeto. 44 | 45 | **Linha 32:** 46 | 47 | **return postagemRepository.findById(Long id):** Retorna a execução do Método **findById(id)**, que é um **Método padrão da Interface JpaRepository**. O Método retornará **um Objeto da Classe Postagem** persistido no Banco de dados (), caso ele seja encontrado a partir do parâmetro Long id. Caso contrário, será retornado um Objeto Nulo. 48 | 49 | **.map(resposta 🡪 ResponseEntity.ok(resposta)):** Se o Objeto da Classe Postagem for econtrado, o Método **map** (Optional), mapeia no **Objeto resp** o Objeto Postagem retornado pelo Método findById(id)), insere o Objeto mapeado no Corpo da Resposta do Método **ResponseEntity.ok(resp);** e retorna o HTTP Status **OK🡪200**. 50 | 51 | **.orElse(ResponseEntity.notFound().build());:** Se o Objeto Postagem não for encontrado (Nulo), será retornado o HTTP Status **NOT FOUND 🡪 404** (Não Encontrado!). O Método **build()** constrói a Resposta com o HTTP Status retornado. 52 | 53 | Para concluir, não esqueça de Salvar o código (**File 🡪 Save All**) e verificar se o Projeto está em execução. 54 | 55 |
56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
76 | 77 | 78 | 79 | 80 |
81 | 82 |

👣 Passo 02 - Testar no Insomnia

83 | 84 | Agora vamos criar a Requisição para o **Método getById()**: 85 | 86 | 1. Clique com o botão direito do mouse sobre a **Pasta Postagem** para abrir o menu e clique na opção **New Request**. 87 | 88 |
89 | 90 | 2. Será criada uma nova Requisição (New Request) dentro da pasta **Postagem**. 91 | 92 |
93 | 94 | 3. Dê um duplo clique sobre a nova requisição (**New Request**), informe o nome da requisição (indicado na imagem abaixo na cor amarela) e pressione a tecla **enter** do seu teclado. 95 | 96 |
97 | 98 | 4. Selecione o Método HTTP que será utilizado (**GET**) na requisição, indicado na imagem abaixo na cor verde. 99 | 100 |
101 | 102 | 5. Configure a requisição conforme a imagem abaixo: 103 | 104 |
105 | 106 | 4. No item marcado em amarelo na imagem acima, informe o endereço (endpoint) da Requisição. A requisição **Consultar postagem por ID** foi configurada da seguinte maneira: 107 | 108 | - A primeira parte do endereço (http://localhost:8080) é o endereço do nosso servidor local. Quando a API estiver na nuvem, ele será substituído pelo endereço da aplicação na nuvem (http://nomedaaplicacao.herokuapp.com). 109 | - A segunda parte do endereço é o **Endpoint** configurado na anotação ***@RequestMapping***, em nosso caso **/postagens**. 110 | - A terceira parte (**/1**) é a variável de caminho (**@PathVariable**) **id**. Informe o id que você deseja procurar. 111 | 112 | 5. Para testar a requisição, com a aplicação rodando, clique no botão . 113 | 114 | 6. O resultado da requisição você confere na imagem abaixo: 115 | 116 |
117 | 118 | 7. Observe que a aplicação quando encontra o Objeto no Banco de dados, além de exibir os dados do Objeto no Corpo da Resposta, respeitando o critério informado na consulta (id 1), ela também retorna um **HTTP Status 200 🡪 OK** (indicado em verde na imagem acima), informando que a Requisição foi bem sucedida! 119 | 120 | 8. Caso o Objeto Postagem não seja encontrado, a aplicação retornará o **HTTP Status 404 🡪 NOT FOUND** (Não encontrado), marcado em laranja na imagem abaixo: 121 | 122 |
123 | 124 |
125 | 126 | 127 | 128 |

129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /03_spring/11.md: -------------------------------------------------------------------------------- 1 | 

Projeto 02 - Blog Pessoal - Classe PostagemController - Método Deletar

2 | 3 | O que veremos por aqui: 4 | 5 | 1. Criar o Método delete(Long id) para excluir uma Postagem no Banco de Dados 6 | 7 |

1. O Recurso Postagem

8 | 9 | Nas etapas anteriores, construímos a Classe **PostagemController** e implementamos os Métodos: 10 | 11 | - **getAll()** 🡪 Retorna todos os Objetos da Classe Postagem. 12 | 13 | - **getById(Long id)** 🡪 Retorna um Objeto específico da Classe Postagem persistidos no Banco de dados. A Postagem é identificada pelo Atributo id. 14 | 15 | - **getByTitulo(String titulo)** 🡪 Retorna todos os Objetos da Classe Postagem persistidos no Banco de dados, cujo Atributo titulo contenha a String enviada no parâmetro titulo do Método. 16 | 17 | - **Método post(Postagem postagem)** 🡪 Persiste (salva) um novo Objeto da Classe Postagem no Banco de dados 18 | 19 | - **Método put(Postagem postagem)** 🡪 Atualiza um Objeto da Classe Postagem persistido no Banco de dados. 20 | 21 |
22 | 23 | Vamos finalizar a construção da Classe Controladora com o **Método delete(Long id)**. 24 | 25 |

👣 Passo 01 - Criar o Método delete(Long id)

26 | 27 | Vamos implementar o Método **delete(Long id)** na Classe Postagem Controller. Traçando um paralelo com o MySQL, seria o equivalente a instrução: DELETE FROM tb_postagens WHERE id = id;. 28 | 29 |
30 | 31 | **Linha 65:** a anotação **@ResponseStatus** indica que o Método **delete(Long id)**, terá uma Response Status específica, ou seja, quando a Resposta da Requisição for positiva, será retornado o **HTTP Status NO_CONTENT 🡪 204**, ao invés do **HTTP Status OK 🡪 200** como resposta padrão. 32 | 33 | **Linha 66:** ** A anotação **@DeleteMapping("/{id}")** mapeia todas as Requisições **HTTP DELETE**, enviadas para um endereço específico (**Endpoint**), dentro do Recurso Postagem, para um Método específico que responderá as requisições, ou seja, ele indica que o Método **delete( Long id )**, responderá a todas as requisições do tipo **HTTP DELETE**, enviadas no endereço **http://localhost:8080/postagens/id**, onde **id** é uma **Variável de Caminho** (Path Variable), que receberá o id da Postagem que será Deletada. 34 | 35 | **Linha 67:** O Método **void delete(@PathVariable Long id)** será do tipo **void** porque ele responda Requisições HTTP (HTTP Request), ao deletar uma Postagem ela deixa de existir, logo não tem nenhum tipo de retorno. Como configuramos a anotação **@ResponseStatus**, ele devolverá uma **Resposta HTTP NO_CONTENT 🡪 204**, indicando que o Objeto deletado não existe mais. Observe que o Método possui um parâmetro do tipo **Long**, chamado **id**. 36 | 37 | **@PathVariable Long id:** Esta anotação insere o valor enviado no endereço do endpoint, na Variável de Caminho **{id}**, no parâmetro do Método **delete( Long id )**; 38 | 39 |
40 | 41 | **Exemplo:** 42 | 43 | http://localhost:8080/postagens/1 44 | 45 | Neste exemplo, o parâmetro **Long id**, do Método delete( Long id ), receberá o valor 1 (Id que será procurado em tb_postagens) 46 | 47 | | |
**ATENÇÃO:** *Por questões de boas práticas e legibilidade do código, a Variável de Caminho e o Parâmetro do Método delete devem possuir o mesmo nome.*
| 48 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 49 | 50 | **Linha 68:** **Optional postagem = postagemRepository.findById(id);:** Cria um **Objeto Optional da Classe Postagem** chamado **postagem**, que receberá o resultado do Método findById(id). Como o Método pode retornar um Objeto Nulo, utilizaremos o Optional para evitar o erro **NullPointerException**. Ao ao invés de utilizarmos o map com as Expressões Lambda, utilizaremos o Optional. 51 | 52 | **Linhas 69 e 70:** Através da estrutura condicional if, checamos se o Objeto postagem está vazio (**postagem.isEmpty()**). Se estiver, geramos um HTTP Status **NOT FOUND 🡪 404** (Não Encontrado!) e como estamos utilizando um Objeto da **Classe ResponseStatusException** (throw new ResponseStatusException(HttpStatus.NOT_FOUND);), as próximas linhas do Método serão ignoradas. 53 | 54 | **Linha 73:**: Executa o Método padrão da Interface JpaRepository deleteById(Long id) e retorna o **HTTP Status NO_CONTENT 🡪 204**, HTTP Status padrão do Método. 55 | 56 | Para concluir, não esqueça de Salvar o código (**File 🡪 Save All**) e verificar se o Projeto está em execução. 57 | 58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
74 | 75 | 76 | 77 | 78 |
79 | 80 |

👣 Passo 02 - Testar no Insomnia

81 | 82 | Agora vamos criar a Requisição para o **delete(Long id)**: 83 | 84 | 1. Clique com o botão direito do mouse sobre a **Pasta Postagem** para abrir o menu e clique na opção **New Request**. 85 | 86 |
87 | 88 | 2. Será criada uma nova Requisição (New Request) dentro da pasta **Postagem**. 89 | 90 |
91 | 92 | 3. Dê um duplo clique sobre a nova requisição (**New Request**), informe o nome da requisição (indicado na imagem abaixo na cor amarela) e pressione a tecla **enter** do seu teclado. 93 | 94 |
95 | 96 | 4. Selecione o Método HTTP que será utilizado (**DELETE**) na requisição, indicado na imagem abaixo na cor verde. 97 | 98 |
99 | 100 | 5. Configure a requisição conforme a imagem abaixo: 101 | 102 |
103 | 104 | 6. No item marcado em amarelo na imagem acima, informe o endereço (endpoint) da Requisição. A requisição **Deletar Postagem** foi configurada da seguinte maneira: 105 | 106 | - A primeira parte do endereço (http://localhost:8080) é o endereço do nosso servidor local. Quando a API estiver na nuvem, ele será substituído pelo endereço da aplicação na nuvem. 107 | - A segunda parte do endereço é o **endpoint** configurado na anotação ***@RequestMapping***, em nosso caso **/postagens/**. 108 | - A terceira parte (**/2**) é a varável de caminho (**@PathVariable**) id. Informe o id da postagem que você deseja apagar. 109 | 110 | 7. Para testar a requisição, com a aplicação rodando, clique no botão . 111 | 112 | 8. O resultado da requisição você confere na imagem abaixo: 113 | 114 |
115 | 116 | 9. Observe que a aplicação retorna apenas um **HTTP Status 204 🡪 NO_CONTENT** (indicado em verde na imagem acima). Este Status indica que a Requisição foi bem sucedida!, o Objeto foi apagado e o seu conteúdo não existe mais. 117 | 118 | 10. Caso o Objeto não seja encontrado, a aplicação retornará o **HTTP Status 404 🡪 NOT FOUND** (Não encontrado), como mostra a figura abaixo (marcado em laranja). 119 | 120 |
121 | 122 |
123 | 124 | 125 | 126 | 127 |

128 | 129 | -------------------------------------------------------------------------------- /03_spring/18.md: -------------------------------------------------------------------------------- 1 |

Teste de Software - JUnit 5 - Introdução

2 | 3 | O teste de software é uma forma de avaliar a qualidade da aplicação e reduzir os riscos de falhas no código ao ser colocado em operação (Produção). Testar não se resume apenas em executar testes e verificar os resultados. **Executar** testes é apenas umas das atividades. Planejamento, análise, modelagem e implementação dos testes, relatórios de progresso, resultado e avaliação da qualidade, também são partes de um **processo de testes**. 4 | Testar software não é somente **verificar** se os requisitos foram atendidos, atribui-se ao teste de software também a **validação**, ou seja, verificar se o sistema atenderá às necessidades do usuário e de outras partes interessadas em seu(s) ambiente(s) operacional(is). 5 | 6 |

1. A Pirâmide de Testes

7 | 8 | A **Pirâmide de Testes** é uma representação gráfica que nos diz para agrupar testes de software em diferentes tipos. A pirâmide ilustra de forma implícita a quantidade de testes que devem ser realizados em tipo, os custos e o tempo de duração. 9 | 10 |
11 | 12 | Observe que os testes na base são mais rápidos e baratos do que os testes no topo da pirâmide. 13 | 14 | Existem três tipos de teste: 15 | 16 | - Teste de Unidade 17 | - Teste de Integração 18 | - Teste End to End (E2E) 19 | 20 |

1.1. Teste de unidade

21 | 22 | Uma unidade pode ser uma função, uma Classe, um pacote ou um subsistema. Portanto, o termo teste de unidade refere-se à prática de testar pequenas unidades do seu código, para garantir que funcionem conforme o esperado. 23 | 24 | O Teste de Unidade é o teste mais comum, porquê além de ser muito rápido é o teste mais barato porquê pode ser criado pela própria pessoa desenvolvedora durante o processo de codificação. 25 | 26 |

1.2. Teste de integração

27 | 28 | Teste de Integração é a fase do teste de software em que os módulos são combinados e testados em conjunto, para checar como os módulos se comportam quando interagem entre sí. 29 | 30 | O Teste de Integração é um pouco mais lento e um pouco mais caro do que o Teste de Unidade porquê aumenta a complexidade. 31 | 32 |

1.3. Teste End to End

33 | 34 | O Teste de ponta a ponta é uma metodologia de teste de software para testar um fluxo de aplicativo do início ao fim. O objetivo deste teste é simular um cenário real do usuário e validar o sistema em teste e seus componentes para integração e integridade dos dados. 35 | 36 | O Teste End to End é mais lento (depende de pessoas para testarem o software como um todo em produção ou versão beta), o que o torna muito mais caro do que os Testes de Unidade e Integração, o que explica serem realizados em menor quantidade. 37 | 38 |

1.4. O que deve ser testado?

39 | 40 | A prioridade sempre será escrever testes para as partes mais complexas ou críticas de seu código, ou seja, aquilo que é essencial para que o código traga o resultado esperado. **Exemplo:** Em um e-commerce a finalização da compra é um ponto crítico da aplicação. 41 | 42 |

2. Spring Boot Testing

43 | 44 | O Spring Boot Testing é parte integrante do Spring Boot e oferece suporte a testes de unidade e testes de integração, utilizando alguns Frameworks de Teste Java. 45 | Ao criar um projeto com o Spring Boot, automaticamente as dependências de testes já são inseridas no projeto como veremos adiante. 46 | 47 |
Documentação Oficial 48 | 49 |

2.1. Spring Testing Annotations

50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 60 | 61 |
Spring Boot TestingDescrição
@SpringBootTest

A anotação @SpringBootTest cria e inicializa o nosso ambiente de testes.

59 |

A opção webEnvironment = WebEnvironment.RANDOM_PORT garante que durante os testes o Spring não utilize a porta da aplicação (em ambiente local nossa porta padrão é a 8080), caso ela esteja em execução. Através da opção, o Spring procura uma porta livre para executar os testes.

62 | 63 | O Spring Boot Testing trabalha de forma integrada com os principais Frameworks de Teste do Mercado tais como: **JUnit**, **MockMVC** (Parte integrante do Spring Boot Testing), entre outros. Para escrever os nossos testes utilizaremos o **JUnit 5**. 64 | 65 |

3. O framework JUnit

66 | 67 | O JUnit é um Framework de testes de código aberto para a linguagem Java, que é usado para escrever e executar testes automatizados e repetitivos, para que possamos ter certeza que nosso código funciona conforme o esperado. 68 | 69 | O JUnit fornece: 70 | 71 | • Asserções para testar os resultados esperados. 72 | • Recursos de teste para compartilhar dados de teste comuns. 73 | • Conjuntos de testes para organizar e executar testes facilmente. 74 | • Executa testes gráficos e via linha de comando. 75 | 76 | O JUnit é usado para testar: 77 | 78 | • Um objeto inteiro 79 | • Parte de um objeto, como um Método ou alguns Métodos de interação 80 | • Interação entre vários objetos 81 | 82 |
Documentação: JUnit 5 83 | 84 |

3.1. Anotações do JUnit

85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 126 |
JUnit 5Descrição
@TestA anotação @Test indica que o Método deve ser executado como um teste.
@BeforeEachA anotação @BeforeEach indica que o Método deve ser executado antes de cada Método da Classe, para criar pré-condições necessárias para cada teste (criar variáveis, por exemplo).
@BeforeAllA anotação @BeforeAll indica que o Método deve ser executado uma única vez antes de todos os Métodos da Classe, para criar algumas pré-condições necessárias para todos os testes (criar objetos, por exemplo).
@AfterEachA anotação @AfterEach indica que o Método deve ser executado depois de cada teste para redefinir algumas condições após rodar cada teste (redefinir variáveis, por exemplo).
@AfterAllA anotação @AfterAll indica que o Método deve ser executado uma única vez depois de todos os testes da Classe, para redefinir algumas condições após rodar todos os testes (redefinir objetos, por exemplo).
@DisabledA anotação @Disabled desabilita temporariamente a execução de um teste específico. Cada Método que é anotado com @Disabled não será executado.
@DisplayNamePersonaliza o nome do teste permitindo inserir um Emoji (tecla Windows + . ) e texto.
@TestInstance 121 | A anotação @TestInstance permite modificar o ciclo de vida da Classe de testes. 122 |
A instância de um teste possui dois tipos de ciclo de vida: 123 |

1) O LifeCycle.PER_METHOD: ciclo de vida padrão, onde para cada Método de teste é criada uma nova instância da Classe de teste. Quando utilizamos as anotações @BeforeEach e @AfterEach é necessário utilizar esta anotação. 124 |

2) O LifeCycle.PER_CLASS: uma única instância da Classe de teste é criada e reutilizada entre todos os Métodos de teste da Classe. Quando utilizamos as anotações @BeforeAll e @AfterAll é necessário utilizar esta anotação. 125 |
127 | 128 |

3.2. Asserções - JUnit

129 | 130 | Asserções (Assertions) são Métodos utilitários para testar afirmações em testes (1 é igual a 1, por exemplo). 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 160 | 161 | 162 | 163 | 165 | 166 | 167 | 168 | 169 | 170 | 171 |
AssertionDescrição
assertEquals(expected value, actual value)Afirma que dois valores são iguais.
assertTrue(boolean condition)Afirma que uma condição é verdadeira.
assertFalse(boolean condition)Afirma que uma condição é falsa.
assertNotNull()Afirma que um objeto não é nulo.
assertNull(Object object)Afirma que um objeto é nulo.
assertSame(Object expected, Object 159 | actual)Afirma que dois objetos referem-se ao mesmo objeto.
assertNotSame(Object expected, Object 164 | actual)Afirma que dois objetos não se referem ao mesmo objeto.
assertArrayEquals(expectedArray, resultArray)Afirma que array esperado e o array resultante são iguais.
172 | 173 | | |

**DICA:** *Ao escrever testes, sempre verifique se a importação dos pacotes do JUnit na Classe de testes estão corretos. O JUnit 5 tem como pacote base org.junit.jupiter.api como vocês podem ver no exemplo nesse [link](https://github.com/junit-team/junit5-samples/tree/r5.8.2/junit5-jupiter-starter-maven) .*

| 174 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 175 | 176 |

4. Banco de Dados H2

Tutorial Banco de dados H2 181 | 182 |

5. Quais testes faremos?

183 | 184 | Vamos criar testes nas Camadas **Repository** e **Controller/Service** do Recurso **Usuario** do Projeto Blog Pessoal. 185 | Para executarmos os testes, faremos algumas configurações na Source Folder de testes src/test, algumas configurações no arquivo pom.xml e algumas alterações na **Classe Usuario** e na **Interface UsuarioRepository**. 186 | Antes de prosseguir, assegure que o seu projeto Blog Pessoal não esteja em execução no STS. 187 | 188 |

189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /03_spring/19.md: -------------------------------------------------------------------------------- 1 |

Teste de Software - JUnit 5 - Configurando o Ambiente de testes

2 | 3 | 4 |

👣 Passo 01 - Configurações das Dependências

5 | 6 | Neste passo vamos configurar a Dependência Spring Boot Starter Test (adicionada na criação do projeto) e adicionar a Dependência do Banco de dados em memória H2. 7 | 8 |

1. Configurar a Dependência Spring Testing

9 | 10 | Vamos Configurar a Dependência Spring Boot Starter Test para aceitar apenas o **JUnit 5**. No arquivo, **pom.xml**, vamos alterar a dependência Springboot Starter Test conforme o código abaixo: 11 | 12 | ```xml 13 | 14 | org.springframework.boot 15 | spring-boot-starter-test 16 | test 17 | 18 | 19 | org.junit.vintage 20 | junit-vintage-engine 21 | 22 | 23 | 24 | ``` 25 | *Essa alteração irá ignorar as versões anteriores ao **JUnit 5** (vintage). 26 | 27 |

2. Adicionar a Dependência do Banco de Dados H2

28 | 29 | Para utilizar o Banco de Dados H2 no seu projeto será necessário inserir a Dependência no seu arquivo **pom.xml**. No arquivo, **pom.xml**, vamos adicionar as linhas abaixo: 30 | 31 | ```xml 32 | 33 | com.h2database 34 | h2 35 | test 36 | 37 | ``` 38 | 39 | *Sugerimos adicionar esta dependência logo abaixo da dependência do MySQL. 40 | 41 |
Código fonte: pom.xml 42 |
43 | 44 |

👣 Passo 02 - Criar os Métodos Construtores na Classe Usuario (Camada Model)

45 | 46 | Na **Classe Usuario**, na camada Model, vamos criar 2 Métodos construtores: o primeiro com todos os Atributos (exceto o Atributo postagens, que tem a função de listar as postagens associadas ao usuário, logo é um Atributo preenchido automaticamente pelo Relacionamento entre as Classes) e um segundo Método construtor vazio, ou seja, sem Atributos como mostra o trecho de código abaixo. Através destes dois Métodos iremos instanciar alguns objetos da Classe Usuario nas nossas Classes de teste. 47 | 48 | ```java 49 | public Usuario(Long id, String nome, String usuario, String senha, String foto) { 50 | this.id = id; 51 | this.nome = nome; 52 | this.usuario = usuario; 53 | this.senha = senha; 54 | this.foto = foto; 55 | } 56 | 57 | public Usuario() { } 58 | ``` 59 | 60 | 1. Para criar o Primeiro Construtor, posicione o cursor após o último Atributo da Classe (em nosso exemplo postagem) e clique no menu **Source 🡪 Generate Constructor using fields**. 61 | 62 | 2. Na janela **Generate Constructor using fields**, selecione todos os Atributos, exceto postagem e marque a opção **Omit call to default constructor super()** como mostra a figura abaixo: 63 | 64 |
65 | 66 | 3. Clique no botão **Generate** para concluir. O Construtor será gerado com todas as anotações nos parâmetros, como mostra a figura abaixo: 67 | 68 | ```java 69 | public Usuario(Long id, @NotNull(message = "O Atributo Nome é Obrigatório!") String nome, 70 | @NotNull(message = "O Atributo Usuário é Obrigatório!") @Email(message = "O Atributo Usuário deve ser um email válido!") String usuario, 71 | @NotBlank(message = "O Atributo Senha é Obrigatório!") @Size(min = 8, message = "A Senha deve ter no mínimo 8 caracteres") String senha, 72 | String foto) { 73 | super(); 74 | this.id = id; 75 | this.nome = nome; 76 | this.usuario = usuario; 77 | this.senha = senha; 78 | this.foto = foto; 79 | } 80 | 81 | ``` 82 | 83 | 4. Apague todas as anotações dos parâmetros do Método Construtor. O Método ficará igual ao trecho de código abaixo: 84 | ```java 85 | public Usuario(Long id, String nome, String usuario, String senha, String foto) { 86 | this.id = id; 87 | this.nome = nome; 88 | this.usuario = usuario; 89 | this.senha = senha; 90 | this.foto = foto; 91 | } 92 | ``` 93 | 94 | Agora vamos criar o segundo Método Construtor: 95 | 96 | 1. Posicione o cursor após o Método Construtor com parâmetros e clique no menu **Source 🡪 Generate Constructor using fields**. 97 | 98 | 2. Na janela **Generate Constructor using fields**, desmarque todos os Atributos e marque a opção **Omit call to default constructor super()** como mostra a figura abaixo: 99 | 100 |
101 | 102 | 3. Clique no botão **Generate** para concluir. 103 | 104 | 4. O construtor vazio ficará igual a imagem abaixo: 105 | 106 | ```java 107 | public Usuario() { } 108 | ``` 109 | 110 |
Código fonte: Usuario.java 111 | 112 |

👣 Passo 03 - Atualizar a Interface UsuarioRepository (Camada Repository)

113 | 114 | Na Interface UsuarioRepository, na camada Repository, vamos criar a Query Method **findAllByNomeContainingIgnoreCase(@Param("nome") String nome)** para efetuar alguns testes na Camada Repository. O código da Interface UsuarioRepository atualizado ficará assim: 115 | 116 | ```java 117 | package com.generation.blogpessoal.repository; 118 | 119 | import java.util.Optional; 120 | 121 | import org.springframework.data.jpa.repository.JpaRepository; 122 | import org.springframework.data.repository.query.Param; 123 | import org.springframework.stereotype.Repository; 124 | 125 | import com.generation.blogpessoal.model.Usuario; 126 | 127 | @Repository 128 | public interface UsuarioRepository extends JpaRepository{ 129 | 130 | public Optional findByUsuario(String usuario); 131 | 132 | public List findAllByNomeContainingIgnoreCase(@Param("nome") String nome); 133 | } 134 | ``` 135 | 136 |
Código fonte: UsuarioRepository.java 137 | 138 |

👣 Passo 04 - Configurar o Banco de dados H2

139 | 140 | Agora vamos configurar o Banco de dados H2 para executar os nossos testes sem alterar o Banco de dados principal da aplicação. Como não temos em nosso projeto a pasta **resources**, dentro da **Source Folder src/test**, vamos criar a pasta e na sequência inserir o arquivo **application.properties** para configurarmos o Banco de dados de testes (H2). 141 | 142 | 1) No lado esquerdo superior, na Guia **Package Explorer**, clique sobre a pasta do projeto com o botão direito do mouse e clique na opção **New 🡪 Source folder** 143 | 144 |
145 | 146 | 2) Em **Source Folder**, no item **Folder name**, informe o caminho como mostra a figura abaixo (**src/test/resources**), e clique em **Finish**: 147 | 148 |
149 | 150 | 3) No lado esquerdo superior, na Guia **Package explorer**, na Source Folder **src/test/resources**, clique com o botão direito do mouse e clique na opção **New 🡪 File**. 151 | 152 | 4) Em File name, digite o nome do arquivo (**application.properties**) e clique em **Finish**. 153 | 154 |
155 | 156 | 6) Veja o arquivo criado na **Package Explorer** 157 | 158 |
159 | 160 | 7) Insira no arquivo **application.properties** criado em **src/test/resources** o código abaixo, para configurar o Banco de dados H2: 161 | 162 | ```properties 163 | spring.jpa.hibernate.ddl-auto=create-drop 164 | 165 | spring.datasource.url=jdbc:h2:file:~/target/h2;DB_CLOSE_ON_EXIT=FALSE 166 | spring.datasource.driverClassName=org.h2.Driver 167 | spring.datasource.username=sa 168 | spring.datasource.password=sa 169 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 170 | ``` 171 | | Linha | Descrição | 172 | | ------------------------------------- | ------------------------------------------------------------ | 173 | | **spring.jpa.hibernate.ddl-auto** | Configura o Spring para criar (create) o Banco de dados ao executar a aplicação e apagar (drop) o Banco de dados ao finalizar a aplicação | 174 | | **spring.datasource.url** | Define que o Banco de dados será gerado em um arquivo na pasta target/h2 (jdbc:h2:file:~/target/h2) e o H2 não será fechado até que o STS seja finalizado (DB_CLOSE_ON_EXIT=FALSE) | 175 | | **spring.datasource.driverClassName** | Define o Driver do Banco de dados (H2) | 176 | | **spring.datasource.username** | Define o usuário do H2 (sa) | 177 | | **spring.datasource.password** | Define a senha do usuário do H2 (sa) | 178 | | **spring.jpa.database-platform** | Configura o tipo do Banco de dados (H2). | 179 | 180 |
181 | 182 |
Código fonte: application.properties (src/test/resources) 183 | 184 |

👣 Passo 05 - Criar os pacotes em src/test/java

185 | 186 | Na Source Folder de Testes (**src/test/java**), observe que existe a mesma estrutura de pacotes da Source Folder Principal (**src/main/java**). 187 | 188 |
189 | 190 | Vamos criar em **src/test/java** as packages **Repository** e **Controller**: 191 | 192 | 1. No lado esquerdo superior, na Guia **Package explorer**, clique com o botão direito do mouse sobre a Package **com.generation.blogpessoal**, na Source Folder **src/test/java** e clique na opção **New 🡪 Package**. 193 | 194 | 2. Na janela **New Java Package**, no item **Name**, acrescente no final do nome da Package **.repository**, como mostra a figura abaixo: 195 | 196 |
197 | 198 | 3. Clique no botão **Finish** para concluir. 199 | 200 | 4. **Repita os passos 1-3** para criar a **Package .controller** 201 | 202 | 5. O Resultado você confere na imagem abaixo: 203 | 204 |
205 | 206 |
207 | 208 |
Código fonte do projeto 209 | 210 |

211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /03_spring/20.md: -------------------------------------------------------------------------------- 1 |

Teste de Software - JUnit 5 - Teste da Interface UsuarioRepository

2 | 3 | A Classe **UsuarioRepositoryTest** será utilizada parta testar a Classe Repository do Usuario. 4 | 5 | 1. No lado esquerdo superior, na Guia **Package Explorer**, clique com o botão direito do mouse sobre a Package **com.generation.blogpessoal.repository**, na Source Folder **src/test/java** e clique na opção **New 🡪 Class**. 6 | 7 | 2. Na janela **New Java Class**, no item **Name**, informe o nome da Classe que será o mesmo nome da Classe Principal (**UsuarioRepository**) + a palavra **Test**, para indicar que se trata de uma Classe de Testes, ou seja, **UsuarioRepositoryTest**, como mostra a figura abaixo: 8 | 9 |
10 | 11 | 3. Clique no botão **Finish** para concluir. 12 | 13 | | |
**IMPORTANTE:** *Toda a Classe de teste deve ter no final do seu nome a palavra Test.*
| 14 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 15 | 16 | 17 | | |
**ATENÇÃO:** *O Teste da Classe UsuarioRepository, na camada Repository, utiliza o Banco de Dados, entretanto ele não criptografa a senha ao gravar um novo usuário no Banco de dados porquê ele não utiliza a Classe de Serviço UsuarioService, ele utiliza o Método save(), da Interface JpaRepository de forma direta.*
| 18 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 19 | 20 |

UsuarioRepositoryTest

21 | 22 |
23 | 24 | Na **linha 24** a anotação **@SpringBootTest** indica que a Classe UsuarioRepositoryTest é uma Classe Spring Boot Testing. A Opção **environment** indica que caso a porta principal (8080 para uso local) esteja ocupada, o Spring irá atribuir uma outra porta automaticamente. 25 | 26 | Na **linha 25** a anotação **@TestInstance** indica que o Ciclo de vida da Classe de Teste será por Classe. 27 | 28 | Nas **linhas 28 e 29** foi foi injetado (**@Autowired**), um objeto da Interface UsuarioRepository para persistir os objetos no Banco de dados de testes. 29 | 30 | Entre as **linhas 31 e 42**, o Método **start()**, anotado com a anotação **@BeforeAll**, apaga todos os dados da tabela (linha 34), inicializa 4 objetos do tipo Usuario e insere no Banco de dados de testes através do Método **.save()** uma única vez (**Lifecycle.PER_CLASS**). Observe que em todos os Objetos, o Atributo id está com o valor 0L, indicando que o Atributo será preenchido automaticamente pelo Banco de dados (substituindo o zero pela Chave primária) e o L informa que o Atributo é um Objeto da Classe Long. 31 | 32 |
Documentação: @SpringBootTest 33 | 34 |
Documentação: @TestInstance 35 | 36 |
Documentação: Lifecycle 37 | 38 |
Documentação: @BeforeAll 39 |
40 | 41 |

Método 01 - Retornar um Usuário

42 | 43 |
44 | 45 | Na **linha 46**, o Método **deveRetornarUmUsuario()** foi antotado com a anotação **@Test** que indica que este Método executará um teste. 46 | 47 | Na **linha 47**, a anotação **@DisplayName** configura uma mensagem que será exibida ao invés do nome do Método 48 | 49 | Na **linha 50**, o objeto **usuario** recebe o resultado do Método **findByUsuario()**. 50 | 51 | Na **linha 51**, através do Método de asserção **assertTrue()**, verifica se o usuário cujo e-mail é “joao@email.com.br” foi encontrado. Se o e-mail for encontrado o resultado do teste será: **Aprovado!**. Caso não encontre, o resultado do teste será : **Falhou!**. 52 | 53 |
Documentação: @Test 54 | 55 |
Documentação: @DisplayName 56 | 57 |
Documentação: assertTrue 58 | 59 |

Método 02 - Retornar três Usuários

60 | 61 |
62 | 63 | Na **linha 54**, o Método **deveRetornarTresUsuarios()** foi antotado com a anotação **@Test** que indica que este Método executará um teste. 64 | 65 | Na **linha 55**, a anotação **@DisplayName** configura uma mensagem que será exibida ao invés do nome do Método 66 | 67 | Na **linha 58**, o objeto **listaDeUsuarios** recebe o resultado do Método **findAllByNomeContainingIgnoreCase()**. 68 | 69 | Na **linha 59**, através do Método de asserção **assertEquals()**, verifica se o tamanho da List é igual a 3 (quantidade de usuários cadastrados no Método start() cujo sobrenome é **"Silva"**). O Método size(), (java.util.List), retorna o tamanho da List. Se o tamanho da List for igual 3, o 1° teste será **Aprovado!**. 70 | 71 | Nas **linhas 54 a 56**, através do Método de asserção **AssertTrue()**, verifica em cada posição da Collection List **listaDeUsuarios** se os usuários, que foram inseridos no Banco de dados através no Método start(), foram gravados na mesma sequência. 72 | 73 | - O Teste da **linha 60** checará se o primeiro usuário inserido (João da Silva) está na posição 0 da List **listaDeUsuarios** (1ª posição da List), 74 | - O Teste da **linha 61** checará se o segundo usuário (Manuela da Silva) está na posição 1 da List **listaDeUsuarios** (2ª posição da List). 75 | - O Teste da **linha 62** checará se o terceiro usuário (Adriana da Silva) está na posição 2 da List **listaDeUsuarios** (3ª posição da List). 76 | 77 | A posição na List é obtida através do Método **get(int index)** (java.util.List), passando como parâmetro a posição desejada. O nome do usuário é obtido através do Método **getNome()** da Classe Usuario. Se os três usuários foram gravados na mesma sequência do Método start(), os três testes serão **Aprovados!**. 78 | 79 |
Documentação: assertEquals 80 | 81 |
Documentação: Collection List 82 | 83 |
Documentação: Collection List - Método Size() 84 | 85 |
Documentação: Collection List - Método get(int index) 86 |
87 | 88 | | |

**IMPORTANTE:** cuidado para não confundir o Método get(int index) do pacote java.util.List com o Método get() do pacote java.util.Optional.

| 89 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 90 | 91 | | |

**ATENÇÃO:** *Para que o Método **deveRetornarTresUsuarios()** seja aprovado, as 4 asserções (linhas 59 a 62) devem ser aprovadas, caso contrário o JUnit indicará que o teste Falhou!.*

| 92 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 93 | 94 |
95 | 96 | Entre as **linhas 66 e 69**, o Método **end()**, anotado com a anotação **@AfterAll**, apaga todos os dados da tabela (linha 68), depois que todos os testes foram executados. 97 | 98 | Para concluir, não esqueça de Salvar o código (**File 🡪 Save All**). 99 | 100 | | | **DESAFIO:** Faça algumas alterações nos dados dos objetos e/ou escreva outros testes para praticar. A melhor forma de aprender e compreender como funcionam os testes é praticando! | 101 | | ------------------------------------------------------------ | :----------------------------------------------------------- | 102 | 103 |
104 | 105 | 107 | 108 |

109 | 110 | 112 | 113 | 114 |

115 | 116 | 117 | -------------------------------------------------------------------------------- /03_spring/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Bootcamp - Java Full Stack

5 | 6 |

Backend - Spring

7 | 8 | 1. Introdução ao Spring 9 | 2. Primeiros passos com Spring BOOT 10 | 3. Introdução ao JPA 11 | 4. Projeto Blog Pessoal - Projeto Spring 12 | 5. Projeto Blog Pessoal - Classe Postagem Model 13 | 6. Projeto Blog Pessoal - Interface Postagem Repository 14 | 7. Projeto Blog Pessoal - Classe Postagem Controller - Método Listar tudo 15 | 8. Projeto Blog Pessoal - Classe Postagem Controller - Método Buscar por id 16 | 9. Projeto Blog Pessoal - Classe Postagem Controller - Método Buscar por título 17 | 10. Projeto Blog Pessoal - Classe Postagem Controller - Métodos Cadastrar e Atualizar 18 | 11. Projeto Blog Pessoal - Classe Postagem Controller - Método Apagar 19 | 12. Projeto Blog Pessoal - Relacionamento entre Classes - Recurso Tema - Parte 01 20 | 13. Projeto Blog Pessoal - Relacionamento entre Classes - Recurso Tema - Parte 02 21 | 14. Introdução a Spring Security 22 | 15. Projeto Blog Pessoal - Spring Security - Ecossistema do Usuário 23 | 16. Projeto Blog Pessoal - Spring Security - Ecossistema da Segurança 24 | 17. Projeto Blog Pessoal - Spring Security - Classe de Serviço 25 | 18. Introdução a Spring Testing + JUnit 26 | 19. Projeto Blog Pessoal - Teste Unitário - Configurando o ambiente de testes 27 | 20. Projeto Blog Pessoal - Teste Unitário - Testes na Camada Repository 28 | 21. Projeto Blog Pessoal - Teste Unitário - Testes na Camada Controller 29 | 22. Projeto Blog Pessoal - Documentação com SpringDoc 30 | 23. Projeto Blog Pessoal - Deploy no Render via Github 31 | 32 |

Anexos

33 | 34 | 01. Tipos de dados - Java 35 | 02. Guia do JPA 36 | 03. Diagrama de Classes 37 | 04. Projeto Integrador - Deploy no Render - Organização no Github 38 | 39 |

40 | 41 |
42 |
Home
43 | -------------------------------------------------------------------------------- /03_spring/java_tipos.md: -------------------------------------------------------------------------------- 1 |

Tipos de Dados em Java

2 | 3 |

Tipos de dados primitivos

4 | 5 | | Tipo | Descrição | 6 | | ----------- | ------------------------------------------------------------ | 7 | | **byte** | Tipo de dado inteiro composto por 8 bits. O valor minimo é -128 e o máximo é 127. | 8 | | **short** | Tipo de dado inteiro composto por 16 bits. O valor minimo é -32.768 e o máximo é 32.767. | 9 | | **int** | Tipo de dado inteiro composto por 32 bits. O valor minimo é -2.147.483.648 e o máximo é 2.147.483.648. O tipo int geralmente é utilizado em operações aritméticas para inteiros sem sinal. | 10 | | **long** | Tipo de dado inteiro composto por 64 bits. O valor minimo é -9.223.372.036.854.775.808 e o máximo é 9.223.372.036.854.775.808. O tipo int geralmente é utilizado em operações aritméticas para inteiros sem sinal. | 11 | | **float** | Tipo de dado ponto flutuante (numeros com casas decimais) de 32 bits de precisão simples. O tipo float é usado em operações que precisam economizar memória em grandes matrizes de números de ponto flutuante. Esse tipo de dados nunca deve ser usado para valores precisos, como moeda. Para isso, você precisará usar a Classe [java.math.BigDecimal](https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html) e outras Classes úteis fornecidas pela plataforma Java. | 12 | | **double** | Tipo de dado ponto flutuante (numeros com casas decimais) de 64 bits. O tipo double é tipo de dado padrão para grandes valores com ponto flutuante. Conforme mencionado no tipo float, esse tipo de dados também nunca deve ser usado para valores precisos, como moeda. | 13 | | **boolean** | Tipo de dado composto por apenas dois valores possíveis: `true`e `false`. Use esse tipo de dados para sinalizadores simples que rastreiam condições verdadeiras/falsas. Esse tipo de dados representa um bit de informação, mas seu "tamanho" não é algo definido com precisão. | 14 | | **char** | Tipo de dado composto por um único caractere Unicode de 16 bits. | 15 | 16 |
Documentação: Tipos de dados 17 | 18 |

Classe String

19 | 20 | Em Java, uma string é basicamente um objeto que representa uma sequência de valores char, ou seja um texto. **A Classe Java String** é utilizada para definir uma String e fornecer alguns Métodos para realizar algumas operações com strings como compare(), concat(), equals(), split(), length(), replace(), compareTo(), intern(), substring(), entre outros. 21 | 22 |
Documentação: Classe String 23 | 24 |

Classes Wrappers

25 | 26 | Os **Wrapper** são conhecidos na linguagem Java como Classes especiais, que possuem Métodos capazes de fazer conversões em variáveis primitivas e também de encapsular tipos primitivos para serem trabalhados como objetos, ou seja, converte um primitivo em um Objeto, mantendo as sa características do primitivo e adicionando alguns Métodos para manipular o Objeto. 27 | 28 | 29 | 30 | 35 | 40 | 45 | 46 | 47 | 52 | 57 | 62 | 63 | 64 | 69 | 74 | 79 | 80 | 81 | 86 | 91 | 96 | 97 | 98 | 103 | 108 | 113 | 114 | 115 | 120 | 125 | 130 | 131 | 132 | 137 | 142 | 147 | 148 | 149 | 154 | 159 | 164 | 165 | 166 | 171 | 176 | 181 | 182 |
31 |

32 | Tipo primitivo 33 |

34 |
36 |

37 | Classe Wrapper 38 |

39 |
41 |

42 | Argumentos do construtor 43 |

44 |
48 |

49 | boolean 50 |

51 |
53 |

54 | Boolean 55 |

56 |
58 |

59 | boolean ou String 60 |

61 |
65 |

66 | byte 67 |

68 |
70 |

71 | Byte 72 |

73 |
75 |

76 | byte ou String 77 |

78 |
82 |

83 | char 84 |

85 |
87 |

88 | Character 89 |

90 |
92 |

93 | char 94 |

95 |
99 |

100 | int 101 |

102 |
104 |

105 | Integer 106 |

107 |
109 |

110 | int ou String 111 |

112 |
116 |

117 | float 118 |

119 |
121 |

122 | Float 123 |

124 |
126 |

127 | float, double ou String 128 |

129 |
133 |

134 | double 135 |

136 |
138 |

139 | Double 140 |

141 |
143 |

144 | double ou String 145 |

146 |
150 |

151 | long 152 |

153 |
155 |

156 | Long 157 |

158 |
160 |

161 | long ou String 162 |

163 |
167 |

168 | short 169 |

170 |
172 |

173 | Short 174 |

175 |
177 |

178 | short ou String 179 |

180 |
183 | 184 |

Classe BigDecimal

185 | 186 | Trabalhar com um sistema que manipula valores monetários é uma tarefa crítica e que deve exigir o máximo de atenção do desenvolvedor. Como exemplo, temos sistemas de Caixa de Lojas (PDV), Supermercados, Sistemas Bancários e etc. Um cálculo errado pode ocasionar grandes transtornos para o Banco, assim como em qualquer outra ocasião onde se faz necessária a manipulação de dinheiro. Para resolver esta questão, o Java nos oferece a Classe BigDecimal. 187 | 188 | O grande diferencial da Classe BigDecimal para o Double está na precisão. Enquanto Double trabalha com N casas decimais, o BogDecimal trabalha com uma precisão arbitrária entre 1 e 2 csas decimais, por isso é a melhor opção para trabalhar com operações financeiras. 189 | 190 |
Documentação: Classe BigDecimal 191 | 192 |

Classes LocalDate, LocalDateTime e LocalTime

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 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
RepositórioConteúdo
DocumentaçãoArquivos 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 |
BackendProjeto Spring completo
FrontendProjeto Angular/React Completo
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 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
Preparação do Ambiente
Introdução ao Protocolo HTTP
Banco de dados com MySQL
Spring
Fluxo de trabalho Git
DEVOPS
34 | 35 | --------------------------------------------------------------------------------