![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8046328/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8062463/Clean_Architecture.png)
/me
William Correa
@wilcorrea
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/4768367/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/4768372/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/6339982/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/6368292/photo_2019-03-01_08-56-06.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8060137/pasted-from-clipboard.png)
Primeira coisa que a gente pensa sobre quando falam de código limpo
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8046338/pasted-from-clipboard.png)
Clean Architecture
Robert C. Martin
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8046342/pasted-from-clipboard.png)
Uncle Bob
SOLID
Clean Arch
Clean Code
Onion model
Bereshit bará Elohim et hashamaim veét haárets
toda história tem um começo
STRUCTURED PROGRAMMING
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064038/pasted-from-clipboard.png)
OBJECT-ORIENTED PROGRAMMING
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064040/pasted-from-clipboard.png)
FUNCTIONAL PROGRAMMING
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064048/pasted-from-clipboard.png)
CONCLUSÃO
![](https://media3.giphy.com/media/ckrSh4aCni6dj1vwSe/giphy.gif)
Os paradigmas nos dizem o que não fazer, mais do que eles nos dizem o que fazer
SOLID
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064289/pasted-from-clipboard.png)
1980
Início do debate dos princípios
com outros engenheiros de software.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/842076/images/7940488/uncle-bob-removebg-preview.png)
2000
Depois de adicionar, mesclar e remover princípios, aqui foi estabilizado só que numa ordem aleatória.
2004
Michael Feathers ajudou a organizar os princípios como é apresentado hoje em dia.
SINGLE RESPONSIBILITY PRINCIPLE
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8060373/pasted-from-clipboard.png)
class Customer:
def __init__(self, name: str):
self.name = name
def get_name(self) -> str:
pass
def save(self, customer: Customer):
pass
Muita Responsa
class Customer:
def __init__(self, name: str):
self.name = name
def get_name(self) -> str:
pass
Stonks
class CustomerModel:
def save(self, customer: Customer):
pass
OPEN-CLOSED PRINCIPLE
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8060375/pasted-from-clipboard.png)
class Discount:
def __init__(self, customer, price):
self.customer = customer
self.price = price
def give_discount(self):
if self.customer == 'fav':
return self.price * 0.2
if self.customer == 'vip':
return self.price * 0.4
Se mudar já era
class Discount:
def __init__(self, customer, price):
self.customer = customer
self.price = price
def get_discount(self):
return self.price * 0.2
Stonks
class VIPDiscount(Discount):
def get_discount(self):
return super().get_discount() * 2
LISKOV SUBSTITUTION PRINCIPLE
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8060377/pasted-from-clipboard.png)
class Order:
def __init__(self, output: Output, amount):
self.output = output
self.amount = amount
def save(self):
self.output.export()
Jogo é jogo
class Output:
def save(self):
return self
class PDF (Output):
def save(self):
return self
def export(self):
return self
class Printer (Output):
def save(self):
return self
Stonks
class Order:
def __init__(self, output: Output, amount):
self.output = output
self.amount = amount
def save(self):
self.output.export()
class Output:
def save(self):
return self
def export(self):
return self
class PDF (Output):
def save(self):
return self
def export(self):
return self
class Printer (Output):
def save(self):
return self
INTERFACE SEGREGATION PRINCIPLE
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8060384/pasted-from-clipboard.png)
class Order:
def __init__(self, output: Output, amount):
self.output = output
self.amount = amount
def save(self):
self.output.export()
Cada um no seu quadrado
class Output:
def save(self):
return self
class PDF (Output):
def save(self):
return self
def export(self):
return self
class Printer (Output):
def save(self):
return self
class Order:
def __init__(self, output: OutputExporter, amount):
self.output = output
self.amount = amount
def save(self):
self.output.export()
Stonks
class Output:
def save(self):
return self
class PDF (OutputExporter):
def save(self):
return self
def export(self):
return self
class Printer (Output):
def save(self):
return self
class OutputExporter (Output):
def save(self):
return self
def export(self):
return self
DEPENDENCY INVERSION PRINCIPLE
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8060383/pasted-from-clipboard.png)
class Order:
def __init__(self):
return self
def save(self, amount):
customer = new Customer()
customer.sync(amount)
return self
Escondido é mais gostoso
class Order:
def __init__(self):
return self
def save(self, customer: Customer, amount):
customer.sync(amount)
return self
Stonks
THE CLEAN ARCHITECTURE
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064430/pasted-from-clipboard.png)
![](https://media4.giphy.com/media/l22ysLe54hZP0wubek/giphy.gif)
![](https://media3.giphy.com/media/pyQV6sy5qOALu/giphy.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064300/pasted-from-clipboard.png)
E o MVC?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064428/pasted-from-clipboard.png)
E a Web?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064437/pasted-from-clipboard.png)
E o que mais?
- Hexagonal Architecture (Alistair Cockburn)
- DCI (James Coplien and Trygve Reenskaug )
- BCE (Ivar Jacobson)
- Domain Driven Design (Eric Evans)
CAMADAS e + CAMADAS
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8063977/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8063976/pasted-from-clipboard.png)
![](https://media4.giphy.com/media/5t9wJjyHAOxvnxcPNk/giphy.gif)
![](https://media4.giphy.com/media/5t9wJjyHAOxvnxcPNk/giphy.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064342/pasted-from-clipboard.png)
Tá, e cumé que é isso?!
![](https://media0.giphy.com/media/PiQejEf31116URju4V/giphy.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064376/pasted-from-clipboard.png)
O DESENHO
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064364/pasted-from-clipboard.png)
-
Fácil de testar ou pelo menos testável
-
Regras de negócio manuteníveis
-
Independência de agentes externos
-
Melhoria de percepção na leitura
AS VANTAGENS
REGRAS DE NEGÓCIO
from rentomatic.response_objects import response_objects as res
class RoomListUseCase(object):
def __init__(self, repo):
self.repo = repo
def execute(self, request_object):
if not request_object:
return res.ResponseFailure.build_from_invalid_request_object(
request_object)
try:
rooms = self.repo.list(filters=request_object.filters)
return res.ResponseSuccess(rooms)
except Exception as exc:
return res.ResponseFailure.build_system_error(
"{}: {}".format(exc.__class__.__name__, "{}".format(exc)))
ORGANIZAR INTERESSES
from typing import Optional, List
from pydantic import BaseModel
class Room(BaseModel):
...
class RoomFilter(BaseModel):
code: Optional[str] = None
...
class RoomStorage:
def get_rooms(self, filters: RoomFilter) -> List[Room]: ...
class RoomListUseCase:
def __init__(self, repo: RoomStorage):
self.repo = repo
def show_rooms(self, filters: RoomFilter) -> List[Room]:
rooms = self.repo.get_rooms(filters=filters)
return rooms
REFERÊNCIA
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064416/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064423/pasted-from-clipboard.png)
O DESENHO
Componentes
<template>
<Appform>
<AppInput
name="name"
width="6"
v-model="record.name"
:error="error.name"
/>
<AppInput
name="email"
width="6"
v-model="record.email"
:error="error.email"
/>
<AppTextarea
name="description"
width="6"
v-model="record.description"
:error="error.description"
/>
</AppForm>
</template>
<script>
...
</script>
<template>
<div
class="form-group"
:class="[`col-sm-${width}`]"
>
<label>{{ label }}</label>
<input
class="form-control"
:value="value"
@input="$emit('input', ...)"
/>
</div>
</template>
<script>
export default {
name: 'AppInput',
props: {
value: {
default: () => (undefined)
},
...
}
...
}
</script>
Componentes
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064446/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064447/pasted-from-clipboard.png)
Componentes
REFERÊNCIA
ARQUITETURA LIMPA
+
TESTES
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8064449/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/565984/images/8065246/pasted-from-clipboard.png)
<template>
<div class="PontoVendaComandaConsumacao">
<PontoVendaComandaBarra
:comanda="comanda"
@fechar="confirmarConsumo"
/>
<template v-if="status === 'C'">
<PontoVendaComandaAbertura
:comanda="comanda"
@fechar="fechar"
@abrir="abrir"
/>
</template>
<template v-else>
<div class="flex row">
<div class="col-sm-8 col-md-9">
<template v-if="status === 'P'">
<PontoVendaComandaConta />
</template>
<template v-else-if="status === 'A'">
<PontoVendaComandaCardapio
ref="cardapio"
:categorias="categorias"
@selecionado="selecionarProduto"
/>
</template>
</div>
....
</template>
</div>
</template>
<QItemSection avatar>
<template v-if="complemento.qtdemax === 1">
<!-- radio: { qtdemax === 1 } -->
<QRadio
v-model="selecao[complemento.id]"
:val="item.id"
@input="atualizarValorComplemento(complemento.id)"
/>
</template>
<!-- numeric: { qtdemax > 1 } -->
<template v-else>
<div class="flex">
<QBtn
icon="remove"
:disable="naoPodeDecrementar(complemento, item)"
@click="decrementar(complemento, item)"
/>
<div class="PontoVendaComandaComplemento__valor q-pa-sm">
{{ $util.get(selecao, `${complemento.id}.${item.id}`) }}
<!-- force update -->
<input
type="hidden"
:value="placebo"
>
</div>
<QBtn
icon="add"
disable="naoPodeIncrementar(complemento)"
@click="incrementar(complemento, item)"
/>
</div>
</template>
</QItemSection>
hora das palmas
Clean Architecture
By William Correa
Clean Architecture
- 702