Bad Smells 
em 
Bancos de Dados 
Fabrízio Mello Guilherme Lacerda 
@fabriziomello @guilhermeslac
Quem somos nós? 
Fabrízio de Royes Mello @fabriziomello 
● Desenvolvedor PostgreSQL 
● Líder PostgreSQL Brasil 
● Pós-Graduando Uniritter (Agile) 
● http://fabriziomello.github.io 
Guilherme Silva de Lacerda @guilhermeslac 
● Consultor e Professor Universitário 
● Doutorando em Ciência da Computação 
● http://www.guilhermelacerda.net
Agenda 
● Refatoração e Código vs Refatoração 
em Banco 
● Dívida Técnica 
● Database Smells e Refatorações 
● Considerações Finais
Bancos de Dados 
Tendem a se deteriorar ao longo do 
tempo. Alguns motivos: 
● crescimento volume de 
dados/transações 
● aumento natural de usuários ativos 
● dificuldade na evolução do schema 
● estratégias de manutenção
Refatoração de Banco de Dados 
Deterioração + Mudanças em Requisitos = 
Necessidade de Refatoração 
Mas não é tão simples quanto parece: 
● além de manter comportamento 
também é preciso manter informação 
(dados) 
● acoplamento com diversas origens 
(apps, bds, integrações, 3rd, …)
Code Smell 
“É uma categoria comum de problema no 
código fonte que indica a necessidade de 
refatoração.” (Martin Fowler)
Database Smell 
“Similarmente aos Code Smells existem 
problemas comuns em bancos de dados 
que indicam uma potencial necessidade 
de refatoração” (Scott Ambler)
Database Smell 
Multi-purpose column 
Se uma coluna for utilizada para vários fins, é 
provável que exista um código extra para 
garantir que a mesma seja usada 
corretamente e, muitas vezes, verificando 
valores de uma ou mais colunas.
Multi-purpose column 
CREATE TABLE pessoa ( 
id SERIAL PRIMARY KEY, 
tipo CHAR(1) CHECK (tipo IN ('F', 'J')), 
nome VARCHAR(100) NOT NULL, 
data DATE 
); 
Se tipo = 'F' então DATA = nascimento 
Se tipo = 'J' então DATA = inicio atividades
Multi-purpose column 
Sugestão(ões) de Database Refactoring 
● Split Column 
● Move Column
Database Smell 
Multi-purpose table 
Quanto uma tabela é utilizada para 
armazenar vários tipos de entidades 
provavelmente existe uma falha de projeto.
Multi-purpose table 
CREATE TABLE pessoa ( 
id SERIAL PRIMARY KEY, 
nome VARCHAR(100) NOT NULL, 
nome_fantasia VARCHAR(100), 
cnpj CHAR(14), 
cpf CHAR(11), 
rg CHAR(10) 
); 
Se cnpj e nome_fantasia = NULL então NOME = nome 
pessoa física 
Se cpf e rg = NULL então NOME = razão social
Multi-purpose table 
Sugestão(ões) de Database Refactoring 
● Split Column 
● Move Column 
● Split Table
Database Smell 
Redundant Data 
É um problema sério em bases de dados, 
porque quando o dado é armazenado em 
vários locais, existe risco de ocorrer 
inconsistências.
Redundant Data 
CREATE TABLE sys.usuario ( 
id SERIAL PRIMARY KEY, 
login VARCHAR(100) NOT NULL, 
nome VARCHAR(100) NOT NULL 
); 
CREATE TABLE rh.funcionario ( 
id SERIAL PRIMARY KEY, 
nome VARCHAR(100) NOT NULL, 
endereco VARCHAR(100), 
numero INTEGER, 
complemento VARCHAR(40) 
);
Redundant Data 
Sugestão(ões) de Database Refactoring 
● Merge Tables 
● Move Data 
● Drop Column
Database Smell 
Table with too many columns 
Quando uma tabela tem muitas colunas é 
indicativo de falta de coesão, pois está 
armazenando dados de várias entidades.
Table with too many columns 
CREATE TABLE pessoa ( 
id SERIAL PRIMARY KEY, 
nome VARCHAR(100) NOT NULL, 
end_entrega VARCHAR(200), 
end_cobranca VARCHAR(200), 
end_residenc VARCHAR(200), 
end_profiss VARCHAR(200), 
fone_celular VARCHAR(20), 
fone_casa VARCHAR(20), 
fone_fax VARCHAR(20), 
fone_contato VARCHAR(20) 
);
Table with too many columns 
CREATE TABLE parametro ( 
parametro1 VARCHAR(100), 
parametro2 VARCHAR(100), 
parametro3 VARCHAR(100), 
parametro4 VARCHAR(100), 
parametro5 VARCHAR(100), 
parametro6 VARCHAR(100), 
parametro7 VARCHAR(100), 
parametro8 VARCHAR(100), 
... 
parametroN VARCHAR(100) 
);
Table with too many columns 
Sugestão(ões) de Database Refactoring 
● Split Table 
● Move Column
Database Smell 
Table with too many rows 
Tabelas muito grandes podem nos levar a 
problemas de performance. 
O custo (memória e tempo) para buscar ou 
alterar dados em uma tabela varia de acordo 
com o número de linhas
Table with too many rows 
CREATE TABLE log ( 
logtime TIMESTAMP, 
user_name TEXT, 
context CHAR(10), 
message TEXT, 
detail TEXT 
); 
CREATE TABLE log_200602() INHERITS (log); 
CREATE TABLE log_200603() INHERITS (log); 
... 
CREATE TABLE log_201411() INHERITS (log); 
CREATE TABLE log_201412() INHERITS (log);
Table with too many rows 
Sugestão(ões) de Database Refactoring 
● Split Table 
● Move Rows 
● Move Column
Database Smell 
Smart columns 
Coluna que armazena informações de mais 
de um contexto (concatenação de 
informações)
Smart columns 
CREATE TABLE processo ( 
numero CHAR(10) PRIMARY KEY, 
... 
); 
CREATE TABLE debito ( 
processamento CHAR(15) PRIMARY KEY 
... 
); 
numero = 4 digitos ano + 6 digitos sequencial 
processamento = 4 digitos ano + 6 digitos sequencial + 2 
digitos parcela + 2 digitos total parcelas + 1 digito 
verificador
Smart Columns 
Sugestão(ões) de Database Refactoring 
● Split Column
Database Smell 
Phantom foreign-key 
Quando uma coluna em uma tabela pode 
receber um valor, que dependendo de outra 
coluna, estabelece relacionamento de chave 
estrangeira com outra tabela.
Phantom foreign-key 
CREATE TABLE tabela ( 
... 
tipo INTEGER, 
codigo INTEGER, 
... 
); 
Se TIPO = 1 entao CODIGO é ref. TABELA1 
Se TIPO = 2 entao CODIGO é ref. TABELA2 
Se TIPO = 3 entao CODIGO é ref. TABELA3
Phantom foreign-key 
Sugestão(ões) de Database Refactoring 
● Introduce new table 
● Introduce table constraint 
● Move column
Database Smell 
Wrong data type 
Tipos de dados possuem uma assinatura, 
que descreve as validações mínimas para o 
seu uso.
Wrong data type 
CREATE TABLE pessoa ( 
id SERIAL PRIMARY KEY, 
nome VARCHAR(100) NOT NULL, 
cnpj CHAR(14), 
cpf CHAR(11), 
rg CHAR(10) 
); 
CREATE TABLE atributo_dinamico ( 
nome VARCHAR(100), 
tipo INTEGER, 
valor TEXT 
);
Wrong data type 
Sugestão(ões) de Database Refactoring 
● Replace column
Database Smells 
Smells que detectados pela minha 
experiência (não estão na literatura) 
● Phantom foreign-key 
● Wring data-type 
● Trigger Spaghetti
Database Smells 
Fear of change 
Dentre os database smells citados, devemos 
ter atenção especial a este, pois pode ser 
considerado o pior de todos, pois: 
● inibe inovação 
● reduz a efetividade 
● produz ainda mais bagunça 
● ao longo do tempo a situação fica pior
Considerações Finais 
Área com campo vasto a ser explorado 
● taxonomia dos Database Smells 
● Database Smells primitivos e 
compostos 
Explorar outras formas de detecção 
● métricas, visualização, engenharia 
reversa, dependência cíclica 
Ferramentas de apoio
Dúvidas?
Referências 
● Refactoring Improving the Desing of Existing Code 
(Martin Fowler) 
● Refactoring Databases: Evolutionary Database Design 
(Scott Ambler e Pramod Sadalage) 
● http://martinfowler.com/books/refactoring.html 
● http://agiledata.org/essays/databaseRefactoring.html 
● http://www.agiledata. 
org/essays/databaseRefactoringSmells.html
Obrigado! 
Deixe seu feedback aqui: 
bit.ly/xp-feed 
Bad Smells em Bancos de Dados 
Fabrízio Mello e Guilherme Lacerda 
Conferência sobre Extreme Programming 
em Porto Alegre, dez/2014.

Bad Smells em Bancos de Dados

  • 1.
    Bad Smells em Bancos de Dados Fabrízio Mello Guilherme Lacerda @fabriziomello @guilhermeslac
  • 2.
    Quem somos nós? Fabrízio de Royes Mello @fabriziomello ● Desenvolvedor PostgreSQL ● Líder PostgreSQL Brasil ● Pós-Graduando Uniritter (Agile) ● http://fabriziomello.github.io Guilherme Silva de Lacerda @guilhermeslac ● Consultor e Professor Universitário ● Doutorando em Ciência da Computação ● http://www.guilhermelacerda.net
  • 3.
    Agenda ● Refatoraçãoe Código vs Refatoração em Banco ● Dívida Técnica ● Database Smells e Refatorações ● Considerações Finais
  • 4.
    Bancos de Dados Tendem a se deteriorar ao longo do tempo. Alguns motivos: ● crescimento volume de dados/transações ● aumento natural de usuários ativos ● dificuldade na evolução do schema ● estratégias de manutenção
  • 5.
    Refatoração de Bancode Dados Deterioração + Mudanças em Requisitos = Necessidade de Refatoração Mas não é tão simples quanto parece: ● além de manter comportamento também é preciso manter informação (dados) ● acoplamento com diversas origens (apps, bds, integrações, 3rd, …)
  • 6.
    Code Smell “Éuma categoria comum de problema no código fonte que indica a necessidade de refatoração.” (Martin Fowler)
  • 7.
    Database Smell “Similarmenteaos Code Smells existem problemas comuns em bancos de dados que indicam uma potencial necessidade de refatoração” (Scott Ambler)
  • 8.
    Database Smell Multi-purposecolumn Se uma coluna for utilizada para vários fins, é provável que exista um código extra para garantir que a mesma seja usada corretamente e, muitas vezes, verificando valores de uma ou mais colunas.
  • 9.
    Multi-purpose column CREATETABLE pessoa ( id SERIAL PRIMARY KEY, tipo CHAR(1) CHECK (tipo IN ('F', 'J')), nome VARCHAR(100) NOT NULL, data DATE ); Se tipo = 'F' então DATA = nascimento Se tipo = 'J' então DATA = inicio atividades
  • 10.
    Multi-purpose column Sugestão(ões)de Database Refactoring ● Split Column ● Move Column
  • 11.
    Database Smell Multi-purposetable Quanto uma tabela é utilizada para armazenar vários tipos de entidades provavelmente existe uma falha de projeto.
  • 12.
    Multi-purpose table CREATETABLE pessoa ( id SERIAL PRIMARY KEY, nome VARCHAR(100) NOT NULL, nome_fantasia VARCHAR(100), cnpj CHAR(14), cpf CHAR(11), rg CHAR(10) ); Se cnpj e nome_fantasia = NULL então NOME = nome pessoa física Se cpf e rg = NULL então NOME = razão social
  • 13.
    Multi-purpose table Sugestão(ões)de Database Refactoring ● Split Column ● Move Column ● Split Table
  • 14.
    Database Smell RedundantData É um problema sério em bases de dados, porque quando o dado é armazenado em vários locais, existe risco de ocorrer inconsistências.
  • 15.
    Redundant Data CREATETABLE sys.usuario ( id SERIAL PRIMARY KEY, login VARCHAR(100) NOT NULL, nome VARCHAR(100) NOT NULL ); CREATE TABLE rh.funcionario ( id SERIAL PRIMARY KEY, nome VARCHAR(100) NOT NULL, endereco VARCHAR(100), numero INTEGER, complemento VARCHAR(40) );
  • 16.
    Redundant Data Sugestão(ões)de Database Refactoring ● Merge Tables ● Move Data ● Drop Column
  • 17.
    Database Smell Tablewith too many columns Quando uma tabela tem muitas colunas é indicativo de falta de coesão, pois está armazenando dados de várias entidades.
  • 18.
    Table with toomany columns CREATE TABLE pessoa ( id SERIAL PRIMARY KEY, nome VARCHAR(100) NOT NULL, end_entrega VARCHAR(200), end_cobranca VARCHAR(200), end_residenc VARCHAR(200), end_profiss VARCHAR(200), fone_celular VARCHAR(20), fone_casa VARCHAR(20), fone_fax VARCHAR(20), fone_contato VARCHAR(20) );
  • 19.
    Table with toomany columns CREATE TABLE parametro ( parametro1 VARCHAR(100), parametro2 VARCHAR(100), parametro3 VARCHAR(100), parametro4 VARCHAR(100), parametro5 VARCHAR(100), parametro6 VARCHAR(100), parametro7 VARCHAR(100), parametro8 VARCHAR(100), ... parametroN VARCHAR(100) );
  • 20.
    Table with toomany columns Sugestão(ões) de Database Refactoring ● Split Table ● Move Column
  • 21.
    Database Smell Tablewith too many rows Tabelas muito grandes podem nos levar a problemas de performance. O custo (memória e tempo) para buscar ou alterar dados em uma tabela varia de acordo com o número de linhas
  • 22.
    Table with toomany rows CREATE TABLE log ( logtime TIMESTAMP, user_name TEXT, context CHAR(10), message TEXT, detail TEXT ); CREATE TABLE log_200602() INHERITS (log); CREATE TABLE log_200603() INHERITS (log); ... CREATE TABLE log_201411() INHERITS (log); CREATE TABLE log_201412() INHERITS (log);
  • 23.
    Table with toomany rows Sugestão(ões) de Database Refactoring ● Split Table ● Move Rows ● Move Column
  • 24.
    Database Smell Smartcolumns Coluna que armazena informações de mais de um contexto (concatenação de informações)
  • 25.
    Smart columns CREATETABLE processo ( numero CHAR(10) PRIMARY KEY, ... ); CREATE TABLE debito ( processamento CHAR(15) PRIMARY KEY ... ); numero = 4 digitos ano + 6 digitos sequencial processamento = 4 digitos ano + 6 digitos sequencial + 2 digitos parcela + 2 digitos total parcelas + 1 digito verificador
  • 26.
    Smart Columns Sugestão(ões)de Database Refactoring ● Split Column
  • 27.
    Database Smell Phantomforeign-key Quando uma coluna em uma tabela pode receber um valor, que dependendo de outra coluna, estabelece relacionamento de chave estrangeira com outra tabela.
  • 28.
    Phantom foreign-key CREATETABLE tabela ( ... tipo INTEGER, codigo INTEGER, ... ); Se TIPO = 1 entao CODIGO é ref. TABELA1 Se TIPO = 2 entao CODIGO é ref. TABELA2 Se TIPO = 3 entao CODIGO é ref. TABELA3
  • 29.
    Phantom foreign-key Sugestão(ões)de Database Refactoring ● Introduce new table ● Introduce table constraint ● Move column
  • 30.
    Database Smell Wrongdata type Tipos de dados possuem uma assinatura, que descreve as validações mínimas para o seu uso.
  • 31.
    Wrong data type CREATE TABLE pessoa ( id SERIAL PRIMARY KEY, nome VARCHAR(100) NOT NULL, cnpj CHAR(14), cpf CHAR(11), rg CHAR(10) ); CREATE TABLE atributo_dinamico ( nome VARCHAR(100), tipo INTEGER, valor TEXT );
  • 32.
    Wrong data type Sugestão(ões) de Database Refactoring ● Replace column
  • 33.
    Database Smells Smellsque detectados pela minha experiência (não estão na literatura) ● Phantom foreign-key ● Wring data-type ● Trigger Spaghetti
  • 34.
    Database Smells Fearof change Dentre os database smells citados, devemos ter atenção especial a este, pois pode ser considerado o pior de todos, pois: ● inibe inovação ● reduz a efetividade ● produz ainda mais bagunça ● ao longo do tempo a situação fica pior
  • 35.
    Considerações Finais Áreacom campo vasto a ser explorado ● taxonomia dos Database Smells ● Database Smells primitivos e compostos Explorar outras formas de detecção ● métricas, visualização, engenharia reversa, dependência cíclica Ferramentas de apoio
  • 36.
  • 37.
    Referências ● RefactoringImproving the Desing of Existing Code (Martin Fowler) ● Refactoring Databases: Evolutionary Database Design (Scott Ambler e Pramod Sadalage) ● http://martinfowler.com/books/refactoring.html ● http://agiledata.org/essays/databaseRefactoring.html ● http://www.agiledata. org/essays/databaseRefactoringSmells.html
  • 38.
    Obrigado! Deixe seufeedback aqui: bit.ly/xp-feed Bad Smells em Bancos de Dados Fabrízio Mello e Guilherme Lacerda Conferência sobre Extreme Programming em Porto Alegre, dez/2014.