0% acharam este documento útil (0 voto)
34 visualizações67 páginas

Programação Orientada A Objetos

Enviado por

Julia Ellen
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
34 visualizações67 páginas

Programação Orientada A Objetos

Enviado por

Julia Ellen
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 67

PROGRAMAÇÃO ORIENTADA A OBJETOS

Lucas Pontes

Porto Alegre
BEM-VINDO À
ETCR
Seja muito bem-vindo
ao nosso material
didático! Parabéns pela
iniciativa de ter iniciado
um novo ciclo na sua
vida acadêmica.
Gostaria que soubesse
que nós da ETCR

“Eu canto em estaremos sempre


dispostos a ajudar em
sua nova jornada.
português errado Esperamos que você
aproveite ao máximo o
Acho que o nosso material didático
e que ele possa

imperfeito não contribuir para o seu


sucesso no curso. Caso
tenha alguma dúvida ou
participa do precise de ajuda, por
favor, não hesite em

passado.” entrar em contato


conosco, pelos canais:
https://linktr.ee/etcr.
Renato Russo Acesse abaixo o
catálogo on-line da
Escola.

Atenciosamente,
Coordenação.
Diretor: Carlos Milioli
Diretora Pedagógica: Sheila Guarilha
Coordenadora do Curso: Daiane Medeiros
Diagramação: Andréa Fontoura da Silva
Revisão de Língua Portuguesa: Andréa Fontoura da Silva
Projeto Gráfico e Capa: Andréa Fontoura da Silva
Normalização: Andréa Fontoura da Silva (CRB 10/1416)

FICHA CATALOGRÁFICA
SUMÁRIO

Capítulo 1: Introdução a POO………………………10

Capítulo 2: Fundamentos da POO…………………………………………14

Capítulo 3: Herança…………………………22

Capítulo 4: Polimorfismo………………………………………25

Capítulo 5: Abstração……………………………………………...27

Capítulo 6: Manipulação de Exceções……………29

Capítulo 7:coleções e Estruturas de dados………………………………..31

Cpítulo 8: Padrões de projetos…………………..34

Capítulo 9: Práticas avançadas………………………………………………………...37

Capítulo 10: POO em linguagens modernas……………………………………39

Capítulo 11: Projeto final………………………………………………………………..50

Capítulo 12: Tópicos avançados……………………………………..50


CAPÍTULO 1

INTRODUÇÃO
CAPÍTULO 1
HISTORIA DA PROGRAMAÇÃO
ORIENTADA A OBJETOS

A Programação Orientada a Objetos (POO) tem suas raízes na


década de 1960, com a criação da linguagem **Simula** na Noruega por
Ole-Johan Dahl e Kristen Nygaard. Simula foi a primeira linguagem a
introduzir os conceitos de objetos, classes e herança, embora não
necessariamente com esses nomes1. Esses conceitos foram
fundamentais para a evolução da POO.

Na década de 1970, Alan Kay, trabalhando no Xerox PARC,


desenvolveu a linguagem **Smalltalk**, que popularizou a POO e
introduziu a ideia de que “tudo é um objeto”. Smalltalk foi uma das
primeiras linguagens a implementar completamente os conceitos de
POO, incluindo a interação entre objetos através de
mensagens[2](https://blog.betrybe.com/tecnologia/poo-programacao-
orientada-a-objetos/).

A partir da década de 1990, a POO ganhou ampla aceitação com o


surgimento de linguagens como **C++** e **Java**. Java, em particular,
popularizou a POO devido à sua portabilidade e à capacidade de ser
executada em qualquer plataforma que suportasse a Java Virtual
Machine (JVM).
Conceitos Básicos

A POO é baseada em quatro conceitos principais:

1. Classe: Uma classe é uma estrutura que define as


características e comportamentos de um tipo de objeto. Ela é
composta por atributos (dados) e métodos (funções).

Objeto: Um objeto é uma instância de uma classe. Ele representa


uma entidade concreta que possui estado e comportamento definidos
pela classe.

Encapsulamento: O encapsulamento é a prática de esconder os


detalhes internos de um objeto e expor apenas o que é necessário para a
interação com outros objetos. Isso é feito para proteger os dados e
garantir que eles sejam manipulados de maneira controlada.
Herança: A herança permite que uma classe (subclasse) herde
atributos e métodos de outra classe (superclasse), promovendo a
reutilização de código.
Polimorfismo: O polimorfismo permite que objetos de diferentes
classes sejam tratados como objetos de uma classe comum. Isso é útil
para a criação de código mais flexível e reutilizável.

O paradigma de programação orientada a objetos é um modelo de


análise, projeto e programação que se baseia na aproximação entre o
mundo real e o mundo virtual. Ele utiliza objetos, que são instâncias de
classes, para representar entidades do mundo real e suas interações.

A POO difere de outros paradigmas, como a programação


estruturada, ao enfatizar a modularidade e a reutilização de código. Em
vez de escrever programas como uma sequência de instruções, a POO
organiza o código em objetos que interagem entre si, promovendo uma
maior flexibilidade e manutenção do software.

CAPÍTULO 2
FUNDAMENTOS DE POO

Classes e Objetos

A Programação Orientada a Objetos (POO) é um paradigma de


programação que utiliza "objetos" – instâncias de "classes" – como base
para a construção de programas. Uma classe pode ser vista como um
molde ou projeto que define as características e comportamentos dos
objetos criados a partir dela. Por exemplo, uma classe "Carro" pode ter
atributos como cor, modelo, ano e métodos como acelerar e frear.
Segundo Deitel e Deitel (2011), "uma classe define um tipo de objeto
mais geral, e os objetos são instâncias específicas desse tipo" (p. 123).
Em outras palavras, enquanto a classe é uma definição abstrata, o objeto
é uma realização concreta dessa definição.
Diagrama de Classes UML em Programação Orientada a Objetos
(POO):
O Diagrama de Classes é uma ferramenta visual usada para modelar a
estrutura e as relações entre as classes em um sistema. Ele faz parte da
Unified Modeling Language (UML) e é amplamente utilizado na
engenharia de software. Vamos entender os principais pontos sobre ele:

Representação das Classes:


Cada classe é representada por um retângulo.
O retângulo é dividido em três partes:
Nome da Classe: O nome da classe é colocado na parte superior do
retângulo.
Atributos: Os atributos (variáveis) da classe são listados na parte do
meio.
Métodos: Os métodos (funções) da classe são listados na parte inferior.
Exemplo:
Importância das Classes:
Cada classe no diagrama representa uma tabela no banco de dados.
Encontrar as classes corretas é fundamental para o desenvolvimento do
sistema.
Abstração:
Nem todos os objetos identificados em um cenário são úteis para o
diagrama de classe.
A abstração envolve focar apenas nos aspectos essenciais do cenário.
Passo a Passo para Criar um Diagrama de Classe:
Comece com um cenário qualquer.
Identifique os objetos com características semelhantes.
Abstraia as classes a partir desses objetos.
Estabeleça as ligações e cardinalidades entre as classes.
Desafio: Imagine que você trabalha como Analista de Sistemas em uma
empresa de Service Desk. A empresa deseja adquirir o certificado ISO
9001 em qualidade e precisa controlar os pedidos de suporte/serviço
feitos pelos clientes. Você deve criar um diagrama de classe para iniciar
o desenvolvimento de um novo software.

Atributos e Métodos

Atributos são variáveis que armazenam o estado de um objeto. Eles são


definidos dentro da classe e podem ter diferentes tipos de acesso, como
público, privado ou protegido. Métodos, por outro lado, são funções
definidas dentro da classe que descrevem os comportamentos dos
objetos. Eles manipulam os atributos e interagem com outros objetos.
Larman (2004) aponta que "os métodos de uma classe especificam como
seus objetos se comportam e interagem com outros objetos" (p. 45). Por
exemplo, na classe "Carro", os métodos acelerar e frear modificam os
atributos relacionados à velocidade do carro.

Encapsulamento

Encapsulamento é o princípio de esconder os detalhes internos de um


objeto, expondo apenas o que é necessário para o uso externo. Isso é
feito através de modificadores de acesso, que controlam a visibilidade
dos atributos e métodos de uma classe. O encapsulamento promove a
modularidade e a manutenção do código, pois mudanças internas não
afetam outras partes do programa.
Booch (1994) descreve encapsulamento como "uma técnica para
esconder a complexidade interna e mostrar apenas as funcionalidades
necessárias" (p. 89). Por exemplo, os atributos de um objeto "Carro"
podem ser privados, mas acessados e modificados por métodos públicos
chamados getters e setters.

CAPÍTULO 3
HERANÇA

A Herança possibilita que as classes compartilhem seus atributos,


métodos e outros membros da classe entre si. Para a ligação entre as
classes, a herança adota um relacionamento esquematizado
hierarquicamente.

Na Herança temos dois tipos principais de classe:

Classe Base: A classe que concede as características a uma outra


classe.
Classe Derivada: A classe que herda as características da classe
base.
O fato de as classes derivadas herdarem atributos das classes
bases assegura que programas orientados a objetos cresçam de forma
linear e não geometricamente em complexidade. Cada nova classe
derivada não possui interações imprevisíveis em relação ao restante do
código do sistema.

Com o uso da herança, uma classe derivada geralmente é uma


implementação especifica de um caso mais geral. A classe derivada
deve apenas definir as características que a tornam única.

Por exemplo: uma classe base que serviria como um modelo


genérico pode ser a classe Pessoa com os campos Nome e Idade. Já
uma classe derivada poderia ser Funcionário com os campos Nome e
Idade herdados da classe Pessoa, acrescido do campo Cargo.

De maneira natural, as pessoas visualizam o mundo sendo formado


de objetos relacionados entre si hierarquicamente.

Mais um exemplo: vamos analisar a relação entre animais,


mamíferos e cachorros. Os animais, sob uma descrição abstrata,
apresentam atributos, tais como tamanho, inteligência e estrutura óssea.
Apresentam também aspectos comportamentais como mover-se, dormir,
comer, respirar, etc. Esses atributos e aspectos comportamentais
definem a classe dos animais.

Analisando os mamíferos, que são filhos da classe animais,


veremos atributos detalhados e específicos a ele, como por exemplo, tipo
de dente, pelos e glândulas mamárias.

Assim, podemos afirmar que os mamíferos são classificados como


uma classe derivada dos animais, que por sua vez, são uma classe base
dos mamíferos.

Pela chamada hierárquica de classes, a classe derivada mamíferos


recebe todos os atributos de animais, partindo do princípio que uma
classe derivada recebe por herança todos os atributos de seus
ancestrais.
De maneira natural, as pessoas visualizam o mundo sendo formado
de objetos relacionados entre si hierarquicamente.
Mais um exemplo: vamos analisar a relação entre animais,
mamíferos e cachorros. Os animais, sob uma descrição abstrata,
apresentam atributos, tais como tamanho, inteligência e estrutura óssea.
Apresentam também aspectos comportamentais como mover-se, dormir,
comer, respirar etc. Esses atributos e aspectos comportamentais definem
a classe dos animais.

Exemplo Prático
Suponha que estamos criando um sistema para cadastrar animais.
Começamos com a classe base “Animal”:

Agora, podemos criar classes derivadas, como “Cachorro”, que


herdam os atributos da classe base e adicionam características
específicas.

Consideremos a criação de um cadastro de cachorros do reino


Animal. Entendemos que cada Cachorro é um Animal, mais nem todo
Animal é um Cachorro. Essa relação nos obriga a criar uma extensão da
classe Animal a fim de que a mesma contenha os dados específicos
referentes aos cachorros. Assim, a extensão criada acaba herdando os
membros existentes na definição da classe Animal.
Note que usamos os dois pontos : em nossa classe. Fazendo
assim, informamos à classe que ela herda as características da classe
Animal.

Assim temos a definição da classe Cachorro, que, pela herança,


recebe as características da classe Animal, somadas à definição de seus
próprios membros, no caso ao campo Raca.

Perceba que, se formos ao Program.cs e instanciarmos a classe


Cachorro, temos também acesso aos campos da classe Animal:

Isso também se deve ao fato que foram declarados campos do


tipo public, que nos dá acesso a eles de outra classe usando a herança,
como neste caso.

Operador Base: Por meio deste operador temos acesso à classe


pai. Assim, qualquer referencia feita com o uso do operador base, dentro
de uma classe filha, será apontada diretamente para a classe pai.

Apesar de não recomendado, podemos manter atributos de nomes


iguais nas classes pai e filha. Este procedimento é chamado de hiding.
Quando o usamos, devemos adicionar a instrução new na frente do
atributo da classe derivada, caso contrário o compilador irá enviar um
alerta sobre o uso de hiding.
Para este exemplo crie duas novas classes, a base, que será
chamada de Pai, e a derivada, que será chamada de Filha. Na classe Pai
adicione os seguintes campos:

Na Filha, adicione os campos com o mesmo nome mais com


valores diferentes (note o uso da instrução new) e crie o método que irá
exibir os valores de ambas as classes em tela:
Agora no Program.cs, instancie a classe Filha e chame o método
recém-criado:

A herança múltipla é uma característica da Programação Orientada


a Objetos (POO) que permite que uma classe derivada herde de mais de
uma classe base.No entanto, é importante observar que nem todas as
linguagens de programação suportam herança múltipla.

Por exemplo, em C++ e Python, você pode criar uma classe


derivada que herda de várias classes base. No entanto, em Java, a
herança é restrita a apenas uma classe pai (herança simples), mas você
pode implementar várias interfaces em uma única classe. O uso
indiscriminado da herança múltipla pode tornar o código confuso e difícil
de manter, portanto, é necessário considerar cuidadosamente sua
aplicação.

A herança múltipla em Programação Orientada a Objetos (POO)


tem suas vantagens e desvantagens. Vamos explorá-las:
Vantagens da Herança Múltipla

1. Reaproveitamento de Código: Permite que uma classe derivada


herde funcionalidades de várias classes base. Isso promove o reuso de
código e evita duplicação.
2. Especialização: Classes derivadas podem combinar
características de diferentes classes base, criando hierarquias mais ricas
e especializadas.
3. Flexibilidade: Permite modelar relações complexas entre
classes, como “um objeto é tanto um pássaro quanto um animal”.

Desvantagens da Herança Múltipla

1. Ambiguidade: Se duas classes base tiverem métodos ou


atributos com o mesmo nome, a classe derivada pode enfrentar
ambiguidade ao acessá-los.
2. Complexidade: O uso indiscriminado de herança múltipla pode
tornar o código difícil de entender e manter.
3. Conflitos de Nomenclatura: Nomes de métodos ou atributos
podem entrar em conflito, exigindo resolução manual.
CAPITULO 5
POLIMORFISMO

Polimorfismo é um dos pilares fundamentais da Programação


Orientada a Objetos (POO), juntamente com encapsulamento, herança e
abstração. O termo “polimorfismo” vem do grego e significa “muitas
formas”. Em POO, ele se refere à capacidade de um método ou função
de se comportar de diferentes maneiras, dependendo do objeto que o
invoca.

Definimos Polimorfismo como um princípio a partir do qual as


classes derivadas de uma única classe base são capazes de invocar os
métodos que, embora apresentem a mesma assinatura, comportam-se
de maneira diferente para cada uma das classes derivadas.

O Polimorfismo é um mecanismo por meio do qual selecionamos as


funcionalidades utilizadas de forma dinâmica por um programa no
decorrer de sua execução.

Com o Polimorfismo, os mesmos atributos e objetos podem ser


utilizados em objetos distintos, porém, com implementações lógicas
diferentes.

Por exemplo: podemos assumir que uma bola de futebol e uma


camisa da seleção brasileira são artigos esportivos, mais que o cálculo
deles em uma venda é calculado de formas diferentes.

Outro exemplo: podemos dizer que uma classe


chamada Vendedor e outra chamada Diretor podem ter como base uma
classe chamada Pessoa, com um método chamado CalcularVendas. Se
este método (definido na classe base) se comportar de maneira diferente
para as chamadas feitas a partir de uma instância de Vendedor e para as
chamadas feitas a partir de uma instância de Diretor, ele será
considerado um método polimórfico, ou seja, um método de várias
formas.
Assim podemos ter na classe base o método CalcularVendas:

Na classe Vendedor temos o mesmo método, mais com a


codificação diferente:

O mesmo ocorre na classe Diretor:


Tipos de Polimorfismo

Existem dois tipos principais de polimorfismo:

1. Polimorfismo de Sobrecarga (ou Estático): Ocorre quando várias


funções têm o mesmo nome, mas diferentes assinaturas (número
ou tipo de parâmetros). A decisão sobre qual função chamar é
feita em tempo de compilação.

Polimorfismo de Inclusão (ou Dinâmico): Ocorre quando uma classe


derivada substitui um método de sua classe base. A decisão sobre qual
método chamar é feita em tempo de execução.
Vantagens do Polimorfismo

 Flexibilidade e Reutilização: Permite que o código seja mais


flexível e reutilizável, pois métodos podem ser usados de
maneira genérica.
 Manutenção Simplificada: Facilita a manutenção e a extensão
do código, já que novas classes podem ser adicionadas com
comportamentos específicos sem alterar o código existente.
 Redução de Código Redundante: Evita a duplicação de código,
pois métodos genéricos podem ser definidos na classe base e
sobrescritos conforme necessário.

Exemplo Prático

Vamos considerar um exemplo prático de uma aplicação de vendas.


Suponha que temos uma classe base Funcionario e duas classes
derivadas Vendedor e Gerente, cada uma com um método
calcularBonus.
Neste exemplo, o método `calcularBonus` se comporta de maneira
diferente dependendo do tipo de objeto (`Vendedor` ou `Gerente`),
demonstrando o polimorfismo dinâmico.

Encapsulamento é um dos pilares da Programação Orientada a Objetos


(POO). Ele se refere à prática de esconder os detalhes internos de um
objeto e expor apenas o que é necessário para a interação com outros
objetos. Isso é feito para proteger os dados e garantir que eles sejam
manipulados de maneira controlada e segura.

Como Funciona o Encapsulamento


O encapsulamento é implementado usando modificadores de acesso,
como private, protected e public. Esses modificadores controlam a
visibilidade dos atributos e métodos de uma classe:

private: Os membros da classe só podem ser acessados dentro da


própria classe.
protected: Os membros da classe podem ser acessados dentro da
própria classe e por subclasses.
public: Os membros da classe podem ser acessados por qualquer outra
classe.

Exemplo de Encapsulamento

Vamos considerar um exemplo simples de uma classe ContaBancaria:


Neste exemplo, o atributo saldo é privado, o que significa que ele
não pode ser acessado diretamente de fora da classe. Em vez disso,
métodos públicos (getSaldo, depositar e sacar) são fornecidos para
interagir com o saldo de maneira controlada.

Encapsulamento é a técnica que faz com que detalhes internos do


funcionamento dos métodos de uma classe permaneçam ocultos para os
objetos. Por conta dessa técnica, o conhecimento a respeito da
implementação interna da classe é desnecessário do ponto de vista do
objeto, uma vez que isso passa a ser responsabilidade dos métodos
internos da classe.

Assim que uma classe é criada, seu código e seus dados, os quais
são chamados de membros da classe, são determinados. Esses dados
recebem o nome de variáveis membro ou variáveis de instância. Já o
código tem outra função de formar os métodos, os quais também podem
ser denominados como métodos membro.

Vantagens do Encapsulamento
Proteção de Dados: Garante que os dados internos de um objeto
não sejam alterados de maneira inadequada.
Facilidade de Manutenção: Permite que a implementação interna
de uma classe seja alterada sem afetar outras partes do código que
utilizam essa classe.
Reutilização de Código: Facilita a reutilização de classes em
diferentes partes de um programa ou em diferentes projetos.

CAPITULO 6:
ABSTRAÇÃO

O conceito de abstração consiste em esconder os detalhes de algo,


no caso, os detalhes desnecessários.

No mundo real, utilizamos abstrações o tempo todo. Tudo que não


sabemos como funciona por baixo dos panos pode ser considerado uma
abstração.
Para exemplificar melhor, vamos tomar como exemplo a
concessionária que realiza manutenções no seu carro. Você leva ele até
lá com um problema e ele volta funcionando.

Em suma, pouco importa os detalhes do que aconteceu durante a


manutenção do seu carro, o que importa é que ele voltou funcionando.

Como Funciona a Abstração

Na prática, a abstração permite que os desenvolvedores criem


modelos de objetos do mundo real, focando apenas nas características e
comportamentos importantes. Por exemplo, ao modelar um carro em um
sistema, você pode abstrair apenas os atributos essenciais como marca,
modelo e ano, e métodos como frear, sem se preocupar com os detalhes
internos do motor.

Exemplo de Abstração

Vamos considerar um exemplo simples de uma classe Carro:


Neste exemplo, a classe `Carro` é abstrata e define métodos
abstratos acelerar e frear, que devem ser implementados pelas
subclasses.
Vantagens da Abstração

 Redução da Complexidade: Facilita a compreensão e o


desenvolvimento do sistema ao focar apenas nos aspectos
essenciais.
 Reutilização de Código: Permite a criação de componentes
reutilizáveis e modulares.
 Facilidade de Manutenção: Simplifica a manutenção e a
evolução do sistema, pois mudanças nos detalhes internos não
afetam outras partes do código.

Orientação a objetos: Abstração

Abstração é um dos conceitos mais importantes do paradigma


orientado a objetos e também um de seus pilares.

Neste artigo vamos entender um pouco mais sobre abtrações no


geral e como este conceito se aplica na orientação a objetos.

Abstração na orientação a objetos


Dentro da OOP (Object Oriented Programming -- Programação
Orientada a Objetos) temos diversos conceitos de abtração, como por
exemplo as interfaces e classes que escondam algo.

Abstração na forma simples

Para começarmos com um exemplo mais simples, vamos tomar


como base o seguinte código:
Neste exemplo temos uma classe Order que representa um pedido,
e dentro dela temos uma propridade chamada `Total` que define o valor
total do pedido, e dois métodos, CalculateTotal e AddItem.

Listas → Para saber mais sobre listas, confira a aula "Listas" do


curso Fundamentos da Orientação a Objetos.

Quanto mais contato sua classe tem com o mundo externo, maiores
são os impactos das mudanças quando algo for alterado nela.

Por exemplo, se esta classe estiver sendo utilizada em 20 outros


lugares diferentes e você alterar a propriedade `Total` para `Amount`,
geraria um grande refatoramento.

Embora em alguns cenários isto aconteça e seja necessário, quanto


mais detalhes pudermos esconder sobre nossas classes, melhor.

Olhando novamente para o código, você identifica algo que poderia


mudar?
Se notarmos, o cálculo de total está sendo executado a cada item
adicionado. E se pararmos para pensar melhor, não faz sentido alguém
de fora acionar o método que calcula este pedido.

O pedido por si só, deve saber se gerenciar e com a chamada


ao `CalculateTotal` já sendo feita no método `Add`, podemos
simplesmente marca-lo como privado.

Desta forma, privamos o acesso externo utilizando o modificador de


acesso `private`, tornan o método `CalculateTotal` inacessível
externamente.

Modificadores de acesso: Todos os modificadores de acesso com


exemplos práticos estão no curso Fundamentos da Orientação a Objetos.
Abstração por interfaces

As interfaces funcionam como contratos ([Módulo 1 - Aula 17 -


Fundamentos da Orientação a
Objetos](https://balta.io/cursos/fundamentos-orientacao-objetos)) que
definem o que as implementações (Classes) devem conter.

Em suma as interfaces dizem "O que" e não "Como", sendo assim,


podemos tomar o "Como" como os detalhes e o "O que" como uma
abstração.
Tomando como base a interface acima, tomamos ela como um
contrato que diz que um `Customer` pode ser salvo, mas ela não
diz como isto deve ser feito.

Este conceito de abstração por interfaces nos leva ao princípio DIP


Veja mais sobre aqui que prega o seguinte:

Sempre que puder, dependa de abstrações ao invés de


implementaçõs.

Este simples processo resulta na possibilidade de criação de várias


implementações de um mesmo contrato.

Vamos tomar como base esta primeira implementação, que seria


uma versão do contrato que está direcionada ao uso do Entity
Framework.

Porém, durante os testes de unidade, não podemos depender de


dados externos, logo precisamos simular nosso repositório.

Sendo assim, podemos gerar uma outra implementação, baseada


no contrato IcustomerRepository que vai enganar nossos testes
Pronto, neste momento temos duas implementações
CustomerRepository e FakeCustomerRepository se baseando no
contrato IcustomerRepository.

Aplicando a abstração na prática

Agora vamos para um cenário maior, vamos olhar para o


objeto `OrderHandler` que manipula os pedidos.

Este objeto precisa se comunicar com a base de clientes para


salvar os dados lá, porém, durante os testes, não teremos uma base
para salvar.

Desta forma, nossos testes falhariam, ou teríamos que sempre


preparar uma massa de testes para realizar esta execução.

A saída aqui é Mockar, ou seja, simular que fomos no banco de


dados e algo aconteceu. Então, teremos as versões
do CustomerRepository e FakeCustomerRepository sendo utilizadas.

Testes de unidade → Veja mais sobre Mocks e muitos testes de


unidade no curso Refatorando para Testes de Unidade
Realizando os testes

Tudo o que precisamos fazer agora é instanciar o `OrderHandler`,


que nos obrigará a informar um CustomerRepository.

A boa notícia é que tanto o CustomerRepository quanto


o FakeCustomerRepository são compatíveis, mas neste cenário vamos
ficar com o falso.

Utilizando nos Controllers

Caso estivessemos em um cenário Web com MVC, podemos utilizá-


los também nos controladores.
Dependendo de abstrações

Nosso primeiro passo é depender de abstrações (`interfaces`) e não


de implementações (`classes`). Este motivo deve-se ao fato de uma
interface poder conter várias implementações, enquanto uma classe não
tem essa habilidade.

Injeção de dependência

Neste momento você deve estar se perguntando como ele vai saber
qual implementação chamar, a CustomerRepository ou
a FakeCustomerRepository.

O que vai definir isto é a configuração do Service Locator na sua


aplicação.

Desta forma o ASP.NET sabe qual implementação utilizar, dada


uma interface.
CAPITULO 7:
MANIPULAÇÃO DE EXCEÇÕES

Introdução

A manipulação de exceções é uma técnica essencial na


programação orientada a objetos (POO) que permite lidar com erros e
condições excepcionais de maneira controlada. Exceções são eventos
que ocorrem durante a execução de um programa e interrompem o fluxo
normal de instruções. Elas são usadas para sinalizar erros que não
podem ser previstos durante a compilação

Como Funciona a Manipulação de Exceções

A manipulação de exceções geralmente envolve três blocos


principais:

1. Try: Contém o código que pode gerar uma exceção.


2. Catch: Contém o código que trata a exceção, caso ela ocorra.
3. Finally: Contém o código que será executado independentemente
de uma exceção ter ocorrido ou não.

Exemplo de Manipulação de Exceções

Vamos considerar um exemplo simples em Java:


Neste exemplo, o bloco try contém código que pode gerar uma
exceção. Se uma ArrayIndexOutOfBoundsException ocorrer, o bloco
catch tratará a exceção, e o bloco finally será executado
independentemente do resultado.

Vantagens da Manipulação de Exceções

Separação de Código: Mantém o código principal separado do


código de tratamento de erros, tornando-o mais limpo e legível.
Recuperação de Erros: Permite que o programa recupere de erros
de maneira controlada, sem interromper a execução.
Manutenção: Facilita a manutenção e a depuração do código, pois
os erros são tratados de maneira centralizada.

Tratamento de Exceções

Uma exceção é um sinal que indica que algum tipo de condição


excepcional ocorreu durante a execução do programa. Assim, exceções
estão associadas a condições de erro que não tinham como ser
verificadas durante a compilação do programa.

As duas atividades associadas à manipulação de uma exceção são:


A sinalização de que uma condição excepcional (por exemplo, um
erro) ocorreu, A manipulação (tratamento) da situação excepcional, onde
as ações necessárias para a recuperação da situação de erro são
definidas.

Para cada exceção que pode ocorrer durante a execução do código,


um bloco de ações de tratamento (um *exception handler*) deve ser
especificado. O compilador Java verifica e enforça que toda exceção
"não-trivial" tenha um bloco de tratamento associado.

O mecanismo de manipulação de exceções em Java, embora


apresente suas particularidades, teve seu projeto inspirado no
mecanismo equivalente de C++, que por sua vez foi inspirado em Ada. É
um mecanismo adequado à manipulação de erros síncronos, para
situações onde a recuperação do erro é possível.

A documentação da API Java indica, para cada método, se ele pode


gerar ou não uma ou mais exceções. Por exemplo, na documentação do
método java.lang.Integer.parseInt(String) lê-se, parseInt.

Nesse método, se o argumento (uma string) não representar


adequadamente um valor inteiro decimal (ou seja, composto
exclusivamente pelos caracteres dígitos de 0 a 9, opcionalmente com um
sinal '-' à frente), não será possível gerar um valor inteiro correspondente
e uma exceção de nome NumberFormatException será gerada.

Outro exemplo: a documentação da


classe java.io.InputStream indica que o método read() também pode
gerar uma exceção:
CAPITULO 8:
COLEÇÕES E ESTRUTURAS DE DADOS

Introdução às Coleções

Coleções são estruturas de dados que permitem armazenar e


manipular grupos de objetos de maneira eficiente. Em Programação
Orientada a Objetos (POO), as coleções são fundamentais para
organizar e gerenciar dados, facilitando operações como adição,
remoção, busca e iteração sobre elementos.

Tipos de Coleções

Existem vários tipos de coleções, cada uma com suas


características e usos específicos. Os principais tipos incluem:

Listas: Permitem armazenar elementos em uma sequência ordenada.


Podem conter elementos duplicados e são ideais para situações onde a
ordem dos elementos é importante.

Conjuntos (Sets): Armazenam elementos únicos, ou seja, não permitem


duplicatas. São úteis quando a unicidade dos elementos é necessária.
Mapas (Maps): Armazenam pares chave-valor, permitindo a associação
de uma chave única a um valor específico. São úteis para buscas rápidas
de valores associados a chaves.

Vantagens das Coleções

Flexibilidade: As coleções oferecem uma maneira flexível de


armazenar e manipular dados, adaptando-se a diferentes necessidades.
Eficiência: Estruturas de dados como listas, conjuntos e mapas são
otimizadas para operações específicas, como busca e inserção, tornando
o código mais eficiente.
Reutilização de Código: As coleções são parte de bibliotecas
padrão em muitas linguagens de programação, permitindo a reutilização
de código bem testado e confiável.

Exemplo Prático

Vamos considerar um exemplo prático de uso de coleções em Java


para gerenciar uma lista de alunos em uma turma:
Neste exemplo, usamos uma ArrayList para armazenar objetos
Aluno e iteramos sobre a lista para imprimir os detalhes de cada aluno.

CAPÍTULO 9:
PADRÕES DE PROJETO

Introdução aos Padrões de Projeto

Padrões de projeto, ou design patterns, são soluções reutilizáveis


para problemas comuns que surgem durante o desenvolvimento de
software. [Eles foram popularizados pelo livro “Design Patterns: Elements
of Reusable Object-Oriented Software”, publicado em 1994 pelos autores
Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides,
conhecidos como a Gang of Four. Esses padrões ajudam a criar software
mais flexível, reutilizável e fácil de manter, fornecendo um guia para
resolver problemas recorrentes de design de software.

Padrões Criacionais, Estruturais e Comportamentais

Os padrões de projeto são geralmente classificados em três


categorias principais: criacionais, estruturais e comportamentais

1. Padrões Criacionais: Focam na forma como os objetos são


criados. Eles ajudam a tornar o sistema independente de como seus
objetos são criados, compostos e representados. Exemplos incluem:
Singleton: Garante que uma classe tenha apenas uma instância e
fornece um ponto global de acesso a ela.
Factory Method: Define uma interface para criar um objeto, mas
permite que as subclasses alterem o tipo de objeto que será criado.
Abstract Factory: Fornece uma interface para criar famílias de
objetos relacionados ou dependentes sem especificar suas classes
concretas.
Builder: Separa a construção de um objeto complexo da sua
representação, permitindo a criação de diferentes representações.
Prototype: Permite a criação de novos objetos a partir de uma
instância prototípica, clonando-a.
2. Padrões Estruturais: Lidam com a composição de classes e
objetos para formar estruturas maiores. Eles ajudam a garantir que, ao
compor objetos, o sistema permaneça flexível e eficiente. Exemplos
incluem:
Adapter: Permite que interfaces incompatíveis trabalhem juntas,
convertendo a interface de uma classe em outra esperada pelos clientes.
Composite: Compõe objetos em estruturas de árvore para
representar hierarquias parte-todo, permitindo que clientes tratem objetos
individuais e composições de objetos de maneira uniforme.
Decorator: Adiciona responsabilidades adicionais a um objeto
dinamicamente, fornecendo uma alternativa flexível à subclasse.
Facade: Fornece uma interface simplificada para um conjunto de
interfaces em um subsistema.
Proxy: Fornece um substituto ou marcador para controlar o
acesso a um objeto.
Padrões Comportamentais: Focam na comunicação entre objetos,
ajudando a definir como os objetos interagem e distribuem
responsabilidades. Exemplos incluem:
Chain of Responsibility: Passa uma solicitação ao longo de uma
cadeia de manipuladores, onde cada manipulador decide processar a
solicitação ou passá-la adiante.
Command: Encapsula uma solicitação como um objeto,
permitindo parametrizar clientes com diferentes solicitações, enfileirar ou
registrar solicitações e suportar operações reversíveis.
Observer: Define uma dependência um-para-muitos entre
objetos, de modo que quando um objeto muda de estado, todos os seus
dependentes são notificados e atualizados automaticamente.
Strategy: Define uma família de algoritmos, encapsula cada um
deles e os torna intercambiáveis, permitindo que o algoritmo varie
independentemente dos clientes que o utilizam.
Visitor: Representa uma operação a ser realizada sobre os
elementos de uma estrutura de objeto, permitindo definir uma nova
operação sem mudar as classes dos elementos sobre os quais opera.

Exemplos e Aplicações

Os padrões de projeto são amplamente utilizados em diversas


aplicações de software para resolver problemas específicos de design.
Aqui estão alguns exemplos práticos de como esses padrões podem ser
aplicados:

Singleton: Usado em sistemas de logging, onde é necessário


garantir que apenas uma instância do logger esteja ativa para registrar
eventos.
Factory Method: Utilizado em frameworks que precisam criar objetos
de diferentes tipos, mas onde a criação exata do objeto é delegada às
subclasses.
Adapter: Aplicado em sistemas legados para permitir que novas
funcionalidades sejam integradas sem modificar o código existente.
Observer: Comumente usado em sistemas de eventos, como
interfaces gráficas de usuário (GUIs), onde múltiplos componentes
precisam ser notificados sobre mudanças de estado.

Esses exemplos mostram como os padrões de projeto podem ser


aplicados para resolver problemas específicos de design, promovendo a
reutilização de código e a flexibilidade do sistemas.

CAPITULO 11:
POO EM LINGUAGENS MODERNAS

POO em Java
A Programação Orientada a Objetos (POO) em Java é um dos
paradigmas mais utilizados para o desenvolvimento de software. Java é
uma linguagem fortemente tipada e orientada a objetos, o que significa
que quase tudo em Java é um objeto, com exceção dos tipos primitivos.
Os quatro pilares fundamentais da POO em Java são: encapsulamento,
abstração, herança e polimorfismo
Encapsulamento: Refere-se à prática de esconder os detalhes internos
de um objeto e expor apenas o que é necessário. Isso é feito através de
modificadores de acesso como private, protected e public.
Abstração: Envolve a criação de classes que representam conceitos
genéricos, permitindo que detalhes específicos sejam implementados em
subclasses.

Herança: Permite que uma classe herde propriedades e métodos de


outra classe. Isso promove a reutilização de código e a criação de
hierarquias de classes.
Polimorfismo: Permite que objetos de diferentes classes sejam tratados
como objetos de uma classe comum. Isso é frequentemente utilizado em
métodos que podem aceitar objetos de diferentes tipos.

POO em C#
C# é uma linguagem de programação desenvolvida pela Microsoft que
também é fortemente orientada a objetos. Assim como Java, C# suporta
os quatro pilares da POO: encapsulamento, abstração, herança e
polimorfismo.
Encapsulamento: Em C#, o encapsulamento é realizado através de
propriedades e métodos com diferentes níveis de acesso.
Abstração: Em C#, a abstração é implementada usando classes
abstratas e interfaces.

Herança: C# permite a herança de classes, permitindo que uma classe


derive de outra.
Polimorfismo: Em C#, o polimorfismo é alcançado através de métodos
virtuais e sobrescritos.

POO em Python

Python é uma linguagem de programação de alto nível que suporta


múltiplos paradigmas, incluindo a programação orientada a objetos.
Python é conhecido por sua sintaxe clara e concisa, o que facilita a
implementação de conceitos de POO.
Encapsulamento: Em Python, o encapsulamento é implementado usando
convenções de nomenclatura para indicar a visibilidade dos atributos e
métodos.
Abstração: Python usa classes abstratas e métodos abstratos para
implementar a abstração.

Herança: Python permite a herança de classes, permitindo que uma


classe derive de outra.
Polimorfismo: Em Python, o polimorfismo é alcançado através de
métodos que podem ser sobrescritos em subclasses.

CAPITULO 12:
PROJETO FINAL
Desenvolvimento de um Projeto Completo
Desenvolver um projeto completo é uma tarefa que envolve várias
etapas, desde a concepção inicial até a entrega final. Um projeto bem-
sucedido requer planejamento detalhado, execução cuidadosa e
monitoramento constante. Vamos explorar as principais fases do
desenvolvimento de um projeto completo.
1. Planejamento: Esta fase envolve a definição dos objetivos do projeto,
a criação de um cronograma detalhado e a alocação de recursos. O
planejamento eficaz é crucial para garantir que todas as partes
interessadas estejam alinhadas e que o projeto tenha uma base sólida.
Execução: Durante a execução, as tarefas planejadas são realizadas. É
importante seguir o cronograma e fazer ajustes conforme necessário
para lidar com imprevistos. A comunicação eficaz entre os membros da
equipe é essencial para o sucesso desta fase.

Monitoramento e Controle: Esta fase envolve o acompanhamento do


progresso do projeto e a realização de ajustes para garantir que ele
permaneça no caminho certo. Ferramentas de monitoramento e
relatórios regulares são úteis para manter todos informados sobre o
status do projeto.
Encerramento: No encerramento, o projeto é finalizado e entregue. Esta
fase inclui a revisão do projeto, a documentação das lições aprendidas e
a liberação dos recursos.

Aplicação dos Conceitos Aprendidos


A aplicação dos conceitos aprendidos ao longo do curso é fundamental
para consolidar o conhecimento e desenvolver habilidades práticas.
Vamos considerar um exemplo prático de um sistema de gerenciamento
de biblioteca que utiliza os conceitos de POO, padrões de projeto e TDD

1. POO: Utilizamos classes e objetos para modelar os componentes


do sistema, como livros, usuários e empréstimos.
Padrões de Projeto: Aplicamos o padrão Singleton para garantir que o
sistema de gerenciamento de biblioteca tenha apenas uma instância.

TDD: Escrevemos testes antes de implementar a funcionalidade para


garantir que o código atenda aos requisitos.
Desafios e Soluções
Durante o desenvolvimento de um projeto, diversos desafios podem
surgir. Identificar esses desafios e encontrar soluções eficazes é crucial
para o sucesso do projeto

1. Gerenciamento de Tempo: Manter o projeto dentro do cronograma


pode ser desafiador. Solução: Utilizar ferramentas de gerenciamento de
projetos para monitorar o progresso e ajustar o cronograma conforme
necessário.
2. Comunicação: A falta de comunicação eficaz pode levar a mal-
entendidos e atrasos. Solução: Estabelecer canais de comunicação
claros e realizar reuniões regulares para garantir que todos estejam
alinhados.
3. Qualidade do Código: Manter a qualidade do código pode ser difícil,
especialmente em projetos grandes. Solução: Implementar práticas de
revisão de código e utilizar ferramentas de análise estática para
identificar problemas.
4. Gerenciamento de Recursos: Alocar recursos de maneira eficiente é
essencial para evitar desperdícios. Solução: Planejar cuidadosamente a
alocação de recursos e monitorar seu uso ao longo do projeto.
Quais são as diferenças entre os paradigmas de programação?
Primeiramente, vamos imaginar que você precisa ir até a casa de um
amigo que mora na mesma cidade que a sua. Para fazer isso, existem
diversas opções de transporte, como carro, ônibus, metrô, trem, bicicleta
e a pé. E em algumas dessas opções, há mais de uma forma, de carro
por exemplo você pode ir com um carro seu, de carona, ou via aplicativo.
E em cada uma dessas formas, há vantagens e desvantagens, em
questões de preço, tempo, distância, segurança, conforto,etc.
A mesma coisa acontece nos tipos de paradigmas de programação.
Diferentes tipos de programação buscam solucionar problemas
diferentes, e para a programação se adaptar melhor a esses diferentes
objetivos, a forma de estruturar e organizar o código vai ser diferente
também.
Dessas diferentes estruturas e organizações do código, que vem os
diferentes tipos de programação, sendo grandes grupos de linguagens
com características semelhantes. Sendo os dois principais as linguagens
orientadas a objeto, e as linguagens funcionais.
Programação orientada a objeto (POO)
Primeiro, vamos falar sobre o tipo mais popular de programação, a
programação orientada a objeto, ou POO.
A POO é baseada no conceito de objetos, que são representações de
um dado. Um exemplo simples é um bolo. Um bolo tem o sabor da
massa, da cobertura, cores, tamanho, quem fez, qual é o tamanho de
cada pedaço,etc. Todos esses dados sobre o bolo podem ser
representados em um único objeto, sendo esse o principal elemento nas
linguagens orientadas à objeto.
Uma outra característica muito marcante nas linguagens orientadas a
objeto é o foco mais no como, que no que. Em outras palavras, é mais
importante o caminho para chegar em uma ação, que a ação em si.
Um exemplo disso é a adição de uma nova pessoa usuária. Em POO, a
maior parte do processo seria a montagem de um objeto que represente
essa nova pessoa, e todas as checagens nesse processo. Só no fim do
fluxo que a adição seria feita de verdade. Então o foco foi mais
direcionado à como fazer, do que à ação por si.
Exemplos de linguagens famosas que incluem programação orientada à
objeto são Ruby, Scala, Java, Python,etc.
Programação funcional
A programação funcional por um outro lado é mais focada nas funções
do que nos objetos, buscando criar um código mais limpo, e direto, com
uma menor complexidade que a programação orientada à objetos. Tanto
que um dos conceitos da programação funcional são as funções puras.
As funções puras são funções que estão isoladas do resto do código,
então independente de qualquer outro código que estiver fora do escopo
delas, elas sempre vão dar os mesmo resultados. Algo que não pode ser
garantido em linguagens orientadas à objeto por conta das propriedades
que os objetos podem ter.
A vantagem por trás das funções puras é a simplicidade, e a segurança
delas. Porque não tem nenhum objeto, ou classe que pode afetar a
função, tendo a garantia que recebendo os mesmos inputs, o resultado
sempre será o mesmo.
Exemplos de linguagens famosas que incluem programação funcional
são Haskell, Elixir, Erlang, OCaml,etc.
Mutabilidade de variáveis
Em linguagens orientadas à objetos, por padrão, as variáveis são
mutáveis, enquanto linguagens funcionais têm as variáveis imutáveis por
padrão. Essa diferença vem por conta das funções puras, pois uma das
filosofias da programação funcional é representar o retorno das funções
como o “trabalho pronto”, apenas atribuindo uma variável com esse valor.
 Programação Funcional (PF): Este paradigma trata a computação
como a avaliação de funções matemáticas e evita estados mutáveis
e dados compartilhados. A PF enfatiza funções puras, imutabilidade
e funções de ordem superior. Exemplos de linguagens que
suportam PF incluem Haskell, Scala e Elixir.
BIBLIOGRAFIA
Cuida a forma como é feito a bibliografia:
CUNHA, C., CINTRA, L. F. Nova gramática do português
contemporâneo. 7. ed. São Paulo: Lexikon Editora Digital, 2016.

- Booch, G. (1994). Object-Oriented Analysis and Design with


Applications. Addison-Wesley.
Meyer, B. (1988). Object-Oriented Software Construction. Prentice Hall.
Cardelli, L., & Wegner, P. (1985). On Understanding Types, Data
Abstraction, and Polymorphism. ACM Computing Surveys.
Liskov, B. (1987). Data Abstraction and Hierarchy. Addison-Wesley.
Booch, G. (1994). Object-Oriented Analysis and Design with Applications.
Benjamin/Cummings. Deitel, H. M., &
Deitel, P. J. (2011). Java: How to Program. Prentice Hall.
Larman, C. (2004). Applying UML and Patterns: An Introduction to
Object-Oriented Analysis and Design and Iterative Development. Prentice
Hall.
DevMedia. “Conceitos e Exemplos – Herança: Programação Orientada a
Objetos – Parte 1.” Disponível em: DevMedia. Acesso em 27 de julho de
2024.
Maestro Virtual. “Herança de Programação: Características, Tipos,
Exemplos.” Disponível em: Maestro Virtual. Acesso em 27 de julho de
2024.
Estratégia Concursos. “Herança e Polimorfismo na Programação
Orientada a Objetos.” Disponível em: Estratégia Concursos. Acesso em
27 de julho de 2024.
DevMedia. “Polimorfismo: Programação Orientada a Objetos.” Disponível
em: DevMedia. Acesso em 27 de julho de 2024.
Estratégia Concursos. “Herança e Polimorfismo na Programação
Orientada a Objetos.” Disponível em: Estratégia Concursos. Acesso em
27 de julho de 2024.
Shift Desenvolvimento. “Polimorfismo: O terceiro pilar da orientação a
objetos.” Disponível em: Shift Desenvolvimento. Acesso em 27 de julho
de 2024.
Balta.io. Orientação a Objetos: Abstração. Disponível em: Balta.io.
freeCodeCamp. Abstração na Programação Orientada a Objetos.
Disponível em: freeCodeCamp.
UsandoPY. Desvendando o conceito de Abstração na Programação
Orientada a Objetos. Disponível em: UsandoPY.
Unicamp. Programação Orientada a Objetos - Tratamento de Exceções.
Disponível em: Unicamp.
IFRN. Programação Estruturada e Orientada a Objetos - Tratamento de
Exceções. Disponível em: IFRN.
1: Universidade Federal de Minas Gerais. Programação Orientada a
Objetos - Collections. Disponível em: UFMG.
2: Awari. Aprenda Programação Orientada a Objetos e Estrutura de
Dados: o Guia Completo para Desenvolvedores. Disponível em: Awari.
1: Alura. Design patterns: introdução aos padrões de projeto. Disponível
em: Alura.
2: DIO. Design patterns: Breve introdução aos padrões de projeto.
Disponível em: DIO.
3: XPEducação. Padrões de projeto: o que são? Principais tipos e
vantagens. Disponível em: XPEducação.
4: Udemy. Curso de Design Patterns com C# - Desenvolvimento
Avançado. Disponível em: Udemy.
5: Infologia. Design Patterns: Um Guia para Arquitetar Software
Reutilizável e de Alta Qualidade. Disponível em: Infologia.
6: Escola da Programação. Design Patterns em Desenvolvimento de
Software: Guia Completo para Programadores. Disponível em: Escola da
Programação.
7: TecMundo. 5 passos do Desenvolvimento Orientado a Testes (TDD).
Disponível em: TecMundo.
2: GeekHunter. Entenda o que é refatoração e suas principais técnicas.
Disponível em: GeekHunter.
3: Hora de Codar. Refatoração: o que é, para que serve, como fazer e
benefícios. Disponível em: Hora de Codar.
2: Microsoft Learn. Programação orientada a objeto - C#. Disponível em:
Microsoft Learn.
1: FreeCodeCamp. Princípios de programação orientada a objetos em
Java. Disponível em: FreeCodeCamp.
3: Python Academy. Programação Orientada a Objetos no Python:
Introdução. Disponível em: Python Academy.
3: Observatório 3º Setor. Sustentabilidade no Brasil: quais são os
desafios e soluções? Disponível em: Observatório 3º Setor.
4: Geoambiental. Preservação do Meio Ambiente: Desafios e Soluções
para um Futuro Sustentável. Disponível em: Geoambiental.
2: Escola Educação. Aplicação de conceitos aprendidos em situações
práticas. Disponível em: Escola Educação.
1: Artia. Plano de projeto: passo a passo completo para criar o seu.
Disponível em: Artia.
5: Gartner. As 9 tendências do futuro do trabalho para 2024. Disponível
em: Gartner.
6: Forbes Brasil. As megatendências que moldarão o futuro do mundo.
Disponível em: Forbes.
1: DEV Community. Qual é a diferença entre programação orientada a
objetos e funcional? Disponível em: DEV Community.
2: Blog da Locaweb. Programação funcional e POO: veja as diferenças.
Disponível em: Locaweb.
3: Rock Content. Metodologias Ágeis: como usar Scrum, Lean, Kanban e
Smart. Disponível em: Rock Content.
4: Gran Cursos Online. Metodologias Ágeis: o que são, dinâmicas e
exemplos! Disponível em: Gran Cursos Online.

Você também pode gostar