LIDANDO COM CÓDIGO
DUPLICADO
Evaldo Junior Bento

29/11/2013
CC BY-NC-SA
EVALDO JUNIOR
Tecnólogo em Processamento de Dados
MBA em Gestão Estratégica de TI
Desenvolvedor Web
Uso principalmente PHP
HTML, CSS, JavaScript, SQL...
GNU/Linux - Python - Vim
Dafiti
Unimonte
ESCREVI UM LIVRO DE PHP E MYSQL
CASA DO CÓDIGO

EVALDO10
CONTEÚDO DESTA APRESENTAÇÃO
Déjà vu
Os problemas da duplicação de código
Maneiras de identificar código duplicado
Técnicas para corrigir a duplicação de código
CÓDIGO DUPLICADO
Programando de boa na lagoa quando...
As vezes não sabemos que é um código
duplicado, apenas ficamos com a sensação de
Déjà vu
RELATIVAMENTE COMUM
Você não está sozinho
Duplicação é o número 1 dos "bad smells"
O QUE A DUPLICAÇÃO CAUSA?
TAMANHO DA BASE DE CÓDIGO AUMENTA;
COMPREENSÃO É PREJUDICADA;
MANUTENÇÃO É MAIS TRABALHOSA E MAIS PROPENSA À
FALHAS.
Alterar uma parte pode quebrar outras
A correção de uma parte não corrige outras
COMO O PROBLEMA É CRIADO?
MAIS DE UM PROGRAMADOR;
Equipe do eu sozinho também
FUNCIONALIDADES PARECIDAS NO MESMO SOFTWARE;
Copiar e colar
Preguiça de isolar
Desconhecimento de outras partes
FUNCIONALIDADES PARECIDAS EM SOFTWARES DIFERENTES
DO MESMO PROGRAMADOR/EMPRESA.
Copiar e colar
Poderia ser isolado
UM EXEMPLO DO PROBLEMA:
PÁGINA DE LOGIN
1 - BLOCO COM FORM DE LOGIN
2 - PÁGINA APENAS DE LOGIN
Login com e-mail e senha
EM COMUM:
Terão o mesmo formulário
As mesmas validações
O mesmo comportamento
COMO COSTUMA SER FEITO?
Uma das opções é criada e então é copiada
E OS PROBLEMAS...
Alterações ficam complicadas
E se a autenticação for por CPF ou e-mail?
E se entrar uma API para login via Twitter?
COMO IDENTIFICAR CÓDIGO DUPLICADO
IDENTIFICAÇÃO MANUAL;
Complexa e não exata (além de trabalhosa)
Acontece quando sem querer se esbarra em duplicações
Pode ser encontrada quando se procura
USO DE FERRAMENTAS COMO DIFF, MELD ETC;
Bom, mas tem que saber o que quer
Exemplo:
Classes de clientes e funcionários que podem ser
semelhantes
USO DE FERRAMENTAS DE DETECÇÃO.
CPD (Copy/Paste
Detector)
UM EXEMPLO DO PHPCPD:
$ppp -pors apiain
hcd -rges plcto
Poesn fls
rcsig ie
28/28[+++++++++++++++++++++++]100%
6
6 +++++++++++++++++++++++> 0.0
Fud2 eatcoe wt 25dpiae lnsi 3 fls
on 2 xc lns ih 7 ulctd ie n 1 ie:
-apiainmdl/ot_eee.h:06
plcto/oesCnarcbrpp3-5
apiainmdl/ot_aa.h:06
plcto/oesCnapgrpp3-5
IDENTIFIQUEI! E AGORA?
DRY

Don't Repeat Yourself
DRY
Every piece of knowledge must have a single,
unambiguous, authoritative representation
within a system.
Andy Hunt e Dave Thomas - The Pragmatic Programmer
TÉCNICAS PROCEDURAIS
BIBLIOTECAS DE FUNÇÕES;
Helpers
Extraia as partes repetidas para uma função
UM EXEMPLO BÁSICO
eh '$ .nme_omt$mut 2 '' '';
co R'
ubrfra(aon, , ., ,)
eh '$ .nme_omt$mut 2 '' '';
co R'
ubrfra(aon, , ., ,)
eh '$ .nme_omt$mut 2 '' '';
co R'
ubrfra(aon, , ., ,)
eh '$ .nme_omt$mut 2 '' '';
co R'
ubrfra(aon, , ., ,)
PODE FICAR MELHOR ASSIM:
fnto crec_omt
ucin urnyfra(
$mut
aon,
$oe_ybl='$,
mnysmo
R'
$eias=2
dcml
,
$e =''
dc
,,
$huad ='' {
tosns
.)
rtr $oe_ybl.
eun mnysmo
nme_omt$mut $eias $e,$huad)
ubrfra(aon, dcml, dc tosns;
}
eh crec_omt$mut;
co urnyfra(aon)
OUTRO EXEMPLO
fnto smpssadpgscmet(pss $ae){
ucin u_ot_n_ae_omns$ot, pgs
$oa_omns=0
ttlcmet
;
frah(pssa $ot {
oec $ot s ps)
$oa_omns+ cut$ot>omns;
ttlcmet = on(ps-cmet)
}
frah(pgsa $ae {
oec $ae s pg)
$oa_omns+ cut$ae>omns;
ttlcmet = on(pg-cmet)
}
}

rtr $oa_omns
eun ttlcmet;
OUTRO SEM REPETIR:
fnto smcmet(cmetbe){
ucin u_omns$omnals
$oa_omns=0
ttlcmet
;
frah(cmetbe a $omnal){
oec $omnals s cmetbe
$oa_omns+ cut$omnal-cmet)
ttlcmet = on(cmetbe>omns;
}
}

rtr $oa_omns
eun ttlcmet;

fnto smpssadpgscmet(pss $ae){
ucin u_ot_n_ae_omns$ot, pgs
$oa_omns=smcmet(pss;
ttlcmet
u_omns$ot)
$oa_omns+ smcmet(pgs;
ttlcmet = u_omns$ae)
}

rtr $oa_omns
eun ttlcmet;
CLASSES UTILITÁRIAS.
Helpers
Extraia as partes repetidas para um método
TÉCNICAS OO
EXTRACT METHOD;
EXTRACT METHOD;
Métodos com trechos semelhantes
Extraia para apenas um método e use nos outros
Também pode ser usado para simplificar métodos grandes
EXTRACT METHOD
pbi fnto smAto(
ulc ucin oecin)
{
i ( $hs>eUe(-cnces'oeeto' 'di'){
f ! ti-gtsr)>aAcs(SmScin, Amn)
$hs>eiet'ntuhrzd)
ti-rdrc(/oatoie';
}
i (ti-ev>se(){
f $hs>n-iDv)
$hs>nberflr)
ti-ealPoie(;
}
/ ..
/ .
}
pbi fnto aohrcin)
ulc ucin nteAto(
{
i ( $hs>eUe(-cnces'oeeto' 'di'){
f ! ti-gtsr)>aAcs(SmScin, Amn)
$hs>eiet'ntuhrzd)
ti-rdrc(/oatoie';
}
i (ti-ev>se(){
f $hs>n-iDv)
$hs>nberflr)
ti-ealPoie(;
}
/ ..
/ .
}
EXTRACT METHOD
piaefnto cekemsindi(scin
rvt ucin hcPrisoAmn$eto)
{
i ( $hs>eUe(-cnces$eto,'di'){
f ! ti-gtsr)>aAcs(scin Amn)
$hs>eiet'ntuhrzd)
ti-rdrc(/oatoie';
}
}
piaefnto ealPoie(
rvt ucin nberflr)
{
i (ti-ev>se(){
f $hs>n-iDv)
$hs>nberflr)
ti-ealPoie(;
}
}
pbi fnto smAto(
ulc ucin oecin)
{
$hs>hcPrisoAmn'oeeto';
ti-cekemsindi(SmScin)
$hs>nberflr)
ti-ealPoie(;
/ ..
/ .
}
pbi fnto aohrcin)
ulc ucin nteAto(
{
$hs>hcPrisoAmn'oeeto';
ti-cekemsindi(SmScin)
$hs>nberflr)
ti-ealPoie(;
/ ..
/ .
}
EXTRACT CLASS;
EXTRACT CLASS;
Métodos parecidos/iguais em mais de uma classe
As classes não precisam ser relacionadas
Extraia para outra classe e use como um componente
EXTRACT CLASS
/ Rptd e vro cnrles
/ eeio m áis otolr
piaefnto cekemsindi(scin
rvt ucin hcPrisoAmn$eto)
{
i ( $hs>eUe(-cnces$eto,'di'){
f ! ti-gtsr)>aAcs(scin Amn)
$hs>eiet'ntuhrzd)
ti-rdrc(/oatoie';
}
}
/ Rptd e vro cnrles
/ eeio m áis otolr
piaefnto ealPoie(
rvt ucin nberflr)
{
i (ti-ev>se(){
f $hs>n-iDv)
$hs>nberflr)
ti-ealPoie(;
}
}
EXTRACT CLASS
casAl{
ls c
pbi fnto cekemsin$eto,$oe
ulc ucin hcPriso(scin rl)
{
$p =Ap:eIsac(;
ap
p:gtntne)
i ( $p-gtsr)>aAcs(scin $oe){
f ! ap>eUe(-cnces$eto, rl)
$p-rdrc(/oatoie';
ap>eiet'ntuhrzd)
}
}
}
EXTRACT CLASS
casPoie {
ls rflr
piaefnto ealPoie(
rvt ucin nberflr)
{
$p =Ap:eIsac(;
ap
p:gtntne)
i (ap>n-iDv) {
f $p-ev>se()
$p-ealPoie(;
ap>nberflr)
}
}
}
EXTRACT CLASS
pbi fnto _cntut)
ulc ucin _osrc(
{
$ =nwPoie(;
p
e rflr)
$-ealPoie(;
p>nberflr)
}
pbi fnto smAto(
ulc ucin oecin)
{
$c =nwAl)
al
e c(;
$c-cekemsin'oeeto' 'di';
al>hcPriso(SmScin, Amn)
/ ..
/ .
}
PULL UP FIELD;
PULL UP FIELD;
Duas subclasses com o mesmo campo
Mova o campo para a super classe
FORM TEMPLATE METHOD;
FORM TEMPLATE METHOD;
Métodos praticamente iguais em subclasses
Poucas variações
Não é possível simplesmente mover o método para a
superclasse
Separe as diferenças em métodos com a mesma assinatura
Use os novos métodos no método principal
FORM TEMPLATE METHOD;
DESIGN PATTERNS.
Foco em reuso
Vale muito a pena entender os conceitos
Form Template Method == Template Method
RESUMO
Duplicação é ruim
Causada por preguiça ou desconhecimento
Ferramentas de detecção ajudam
Mas não adianta apenas saber que existe duplicação
Técnicas podem ser usadas
Design Patterns importam
REFERÊNCIAS
ht:/hqtosog
tp/ppaol.r/
ht:/swkpdaogwk/%3Bdg_ulcd
tp/e.iiei.r/iiCC%3iodpiao
ht:/nwkpdaogwk/ulct_oe
tp/e.iiei.r/iiDpiaecd
ht:/nwkpdaogwk/o%7_eetyusl
tp/e.iiei.r/iiDn2trpa_oref
ht:/nwkpdaogwk/ito_ol_o_ttccd_nlss
tp/e.iiei.r/iiLs_ftosfrsai_oeaayi
ht:/nwkpdaogwk/epaemto_atr
tp/e.iiei.r/iiTmlt_ehdpten
ht:/nwkpdaogwk/ai%28%3apagrtm
tp/e.iiei.r/iiRbnE%09Kr_loih
hts/gtu.o/eatabrmn/hcd
tp:/ihbcmsbsineganppp
ht:/oreaigcmrfcoigbdsel-ncd
tp/sucmkn.o/eatrn/a-mlsi-oe
ht:/oreaigcmrfcoigdpiae-oe
tp/sucmkn.o/eatrn/ulctdcd
ht:/oreaigcmrfcoigetatmto
tp/sucmkn.o/eatrn/xrc-ehd
ht:/oreaigcmrfcoigpl-pfed
tp/sucmkn.o/eatrn/ulu-il
ht:/oreaigcmrfcoigfr-epaemto
tp/sucmkn.o/eatrn/omtmlt-ehd
ht:/oreaigcmrfcoigetatcas
tp/sucmkn.o/eatrn/xrc-ls
PERGUNTAS?
OBRIGADO!
CONTATOS

Site: evaldojunior.com.br
E-mail: evaldojuniorbento@gmail.com
about.me/evaldojunior
twitter.com/InFog9

Lidando com Código Duplicado - PHP Conference Brasil 2013