Mais conteúdo relacionado Semelhante a Construindo ERP's com PHP: Desafios em design, manutenção segurança e performance (20) Construindo ERP's com PHP: Desafios em design, manutenção segurança e performance1. Construindo ERP's com PHP
Desafios em design, manutenção segurança e performance
Pablo Dall'Oglio
@pablodalloglio fb/pablodalloglio
2. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #2
Meu caminho
●
Clipper (1994-1998): Comercial, bibliotecas, funções (SIC);
●
Delphi (1998-1999): Automação, componentes;
●
PHP (2000): Gestão Universitária (SAGU);
●
PHP-GTK(2001): PHP só com classes;
●
Agata Report (2001-2006);
●
Gnuteca (2002): Gestão de bibliotecas;
●
PHP-GTK: Criando Aplicações Gráficas com PHP (2004);
●
Design Patterns (2004): Unisinos;
●
PHP: Programando com Orientação a Objetos (2007);
●
Core (2006): Framework MVC, ALFA +10 (2008-...);
●
Mestrado em Engenharia de Software (2008, 2009);
●
Adianti Framework para PHP (2012);
●
Universitário (Zattera), Tabelionato (2TAB), Univates.
3. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #3
Objetivo
●
Bater um papo sobre:
– Vivências, aprendizado;
– Soluções adotadas;
– Coisas que deram certo.
●
Aspectos:
– Modelagem;
– Construção;
– Modelagem;
– Desempenho;
– Segurança.
5. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #5
Concepção
Etimologia. A coisa deve iniciar do jeito certo.
6. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #6
Etimologia
●
Você domina a área de negócios?
– Ex: Apontamento, Protesto, Zoneamento,
Apresentante, Intimação, Sustação, Selo, Emolumento.
●
Crie um glossário, todos devem conhecer os termos;
●
Busque definir conceitos primitivos;
●
Serão as futuras entidades ou atributos;
●
Financeiro: Título, boleto, bloqueto, conta a receber;
●
Ações: Liquidar, pagar, baixar, quitar, cancelar.
●
Outros: Holerite, Francesinha, balancete, fluxo de caixa;
●
Acadêmico: Turma, ofertar disciplina, criar ocorrência;
●
Venda: Orçamento, Pedido de venda, Venda, Fatura;
●
Compra: solicitação, requisição, pedido de compra.
7. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #7
Reflita
●
Não use 2 palavras para a mesma coisa: Ex: Pedido de
compra, Requisição, Solicitação;
●
Não use 1 palavra para coisas distintas: Ex: Reserva de
recurso e agenda de consulta, chamar de agendamento.
Local
Equipamentos
Período tempo
Profissional
Diagnóstico
Horário fixo
8. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #8
Regras e métricas
●
Unifique métricas de negócio:
– Como contar alunos?
– Como calcular o saldo em aberto?
– Elimine exceções: Aqui o juro não incide sobre...
– Como calcular média alunos/curso em compartilhadas?
– Definições ajudam a validar a estrutura, e dar direção.
10. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #10
Sistemas satélites
Até onde vai o ERP?
●
Não crie um SISTEMÃO cheio de responsabilidades;
●
Sistemas devem EVOLUIR de maneira independente;
●
Crie critérios para definir as fronteiras;
– Grau de compartilhamento de informações?
– Perfil de público (alunos, professores, empresas)?
– Compartilha somente base de usuários/autenticação?
●
Defina comunicação via serviços (SOA);
●
Ex: Univates: Inscrições Auth pessoa, lança boleto (ERP);→
●
Ex: Univates: Reserva de recursos Auth, recursos (Totvs);→
●
Ex: Univates: Portal do aluno notas, frequências (ERP).→
Cores
Gigante colapsa
11. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #11
Documente fronteiras
Documente as comunicações entre sistemas
Provedor Consumidor Interface Método Descrição
Módulo de
vendas
Força de vendas VendasInterface LancaVendas Permite o Força de vendas lançar uma
venda diretamente no módulo de
vendas
12. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #12
Foreign Data Wrapper
●
Entidade compartilhada com relacionamentos;
●
Outros BD (oracle, mysql, etc), file (CSV), NoSQL (Redis);
bd2=# CREATE TABLE foo(bar integer);
bd1=# CREATE EXTENSION postgres_fdw;
bd1=# CREATE SERVER conexao_bd2 FOREIGN DATA WRAPPER
postgres_fdw OPTIONS (dbname 'bd2');
bd1=# CREATE USER MAPPING FOR current_user SERVER
conexao_bd2 OPTIONS (user 'bob', password 'secret');
bd1=# CREATE FOREIGN TABLE foo (bar integer) SERVER
conexao_bd2;
●
http://fabriziomello.blogspot.com.br/
●
Mysql FEDERATED Tables Melhor que o dblink
13. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #13
Modelagem purista
●
Modele como deve ser o ideal;
●
Tente não pensar em limitações tecnológicas
– (Ex: tabela ficará grande, particionamento, no antigo
usava chaves compostas...).
●
Performance não deve ser resolvida neste estágio!
●
Nem tudo que deu certo no passado ainda é bom!
Não ouça
aqueles que só
veem problemas
14. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #14
Modelo compreensivo
●
Use metamodelos;
●
Prefira o abstrato;
●
Prefira o dinâmico;
●
Mas não exagere!
●
Nem todos estão preparados!
●
Trabalhe com tipo:
– Ex: TipoVenda;
●
Trabalho com estado;
– Ex: EstadoVenda;
●
Registre trocas de estado.
Separe
15. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #15
Metamodelos
Inscrições
Ex: Concursos funcionários/provas; Eventos/palestras, Mestrado/entrevistas.
Vagas por processo/atividade, tipo de seleção: múltipla/exclusiva.
Compreensivo
16. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #16
Lógica antes: SQL
Aplicação orientada à SQL (BAD)
●
Inserir autor em livro
INSERT INTO autor_livro (autor_id, livro_id)
VALUES ('$autor_id', '$livro_id');
●
Calcular algo
SELECT sum(it.qtde*it.valor) FROM nf, itens it
WHERE nf.id = itens.nf_id AND nf.id = '$nf_id'
●
Percorrer dados relacionados
SELECT * FROM turma, matricula, aluno
WHERE turma.id=matricula.turma_id
AND matricula.id_aluno = aluno.id
AND turma.id = '$turma_id'
Cérebro orientado
à tabelas
Cache em nível
De Datasets
Legibilidade
prejudicada
17. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #17
Lógica depois DDD
Aplicação orientada ao domínio (GOOD)
●
Inserir autor em livro
$livro = new Livro( 10 );
$livro->addAutor( new Autor(8) );
$livro->store();
●
Retornar os itens da Nota Fiscal
$nf = new NotaFiscal(10);
$nf->getTotal();
●
Percorrer dados relacionados
$turma = new Turma(10);
foreach ($turma->getMatriculas() as $matricula) {
print $matricula->aluno->nome;
}
Navegabilidade
Encadeamento
entre relações
Objetos como
Parâmetros.
Pacote completo
Ainda não se preocupe
Com desempenho
foreach ($this->items as $item) {
$total += $item->qtde * $item->valor;
}
foreach ($this->items as $item) {
$total += $item->qtde * $item->valor;
}
18. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #18
Encapsule a complex.
●
Não tenha orgulho de SQL gigantes;
●
Separe relatórios do core;
●
Não implemente lógica no banco;
●
Banco guarda, aplicação trata.
Ver 10 piores SQL
CREATE PROCEDURE `VALIDAVENDA`(IN ICODVENDA int(11), OUT CERRO VARCHAR(60))
BEGIN
SET @CCREDITO = (select vendas.cod_venda from vendas where vendas.cod_venda = ICODVENDA
and vendas.status = 1);
SET @PRODUTO = (select vendas.cod_prod from vendas where vendas.cod_venda = ICODVENDA
and vendas.status = 0);
SET @COD_TITULO = (select contas_receber.cod_titulo from contas_receber where
contas_receber.cod_venda = ICODVENDA);
SELECT IF(@CCREDITO IS NULL,'OK','Já existe credito para a venda referente a
devolução!') INTO CERRO;
IF CERRO = 'OK' THEN
UPDATE PRODUTO SET PRODUTO.FLAG_VENDA = "N" WHERE PRODUTO.COD_PROD = @PRODUTO;
19. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #19
Use engenharia
Estimule a especificação. Gere artefatos.
http://uml2php5.zpmag.com (dia2php)
20. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #20
Gere artefatos
<?php
/**
* Customer Active Record
* @author <your-name-here>
*/
class Customer extends TRecord
{
public function get_city()
public function addSkill(Skill $skill)
public function getSkills()
public function load($id)
public function store()
public function delete($id = NULL)
}
XMI
SQL
PHP
Gere código
Gere banco
21. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #21
Simplifique o ORM
●
Primary key simples;
● Active Record. Simplifique: Matricula::find(123);
●
Persistência RAM <=> BD (Identity Field);
●
Cache pelo ID do objeto (APC, Redis);
●
Excluir, manutenção em registros pelo terminal;
●
Chave estrangeira mais simples, não composta.
– Ex: ref contrato na matrícula (pessoa, curso, campus);
●
Joins inner e left são mais fácil e rápido de fazer;
●
Identificar o registro específico em logs de alteração;
●
REST fazer requisição identificando várias chaves.
22. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #22
Cartilha do developer
●
Conhecimento se perde ao longo dos anos;
●
Nomes de classes substantivos, singular;
●
Métodos com verbos (ação);
●
Métodos devem fazer algo OU retornar algo;
●
Classes devem representar 1 coisa;
●
Métodos fazer 1 coisa;
●
Contra exemplo: User::authenticate() já iniciar sessão;
●
Model nunca enviar para a UI (crontab, web);
●
Use exceptions, nunca retorno de erros;
●
Exceptions tratadas na controller;
●
Transactions inside exceptions.
!tb_, verbo...
!Salva, upload
23. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #23
Manutenção
●
Às vezes é interessante separar as coisas.
24. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #24
Acoplamento
●
Muitos desenvolvedores integram bibliotecas assim:
Alto acoplamento: Até pode funcionar, mas...
25. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #25
●
É quanto um módulo (classe, método)
conhece e depende de outro;
●
Baixo:
– Não depende de muitas outras;
– Menos efeitos colaterais em
modificações.
●
Alto:
– Menos reutilizável sozinha;
– Mais sensível à mudanças.
●
O objetivo é criar modelos com baixo
acoplamento;
●
É impossível acoplamento ZERO;
Acoplamento
27. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #27
Facade
●
Facade ajuda a diminuir o acoplamento;
●
Oferece uma interface única para um conjunto de
interfaces de um subsistema;
●
A APP ficará dependente da Facade, não do subsistema.
APP
28. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #28
Facade
<?php
if ($paymenttype_id == 1) // PAGSEGURO
{
$paymentRequest = new PagSeguroPaymentRequest();
$item = new PagSeguroItem;
$item->setDescription( $product->description );
$item->setQuantity( $data->amount );
$item->setAmount( $price );
$paymentRequest->addItem($item);
$address = new PagSeguroAddress;
$address->setPostalCode( $customer->postal );
$address->setStreet( $customer->address );
$address->setCity( $customer->city );
$paymentRequest->setShippingAddress($address);
$sender = new PagSeguroSender;
$sender->setName( $customer->name );
$sender->setEmail( $customer->email );
$paymentRequest->setSender($sender);
}
29. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #29
Facade
<?php
else if ($paymenttype_id == 2) // PAYPAL
{
$total = ($product->price * $data->amount);
// dados para enviar para o paypal
$padata ='&CURRENCYCODE='.urlencode($ini['currency']).
'&PAYMENTACTION=Sale'.
'&ALLOWNOTE=1'.
'&PAYMENTREQUEST_0_AMT='.$total.
'&PAYMENTREQUEST_0_ITEMAMT='.$total.
'&L_PAYMENTREQUEST_0_QTY0='. $data->amount.
'&L_PAYMENTREQUEST_0_AMT0='.$product->price.
'&L_PAYMENTREQUEST_0_NAME0='.$product->description.
'&L_PAYMENTREQUEST_0_NUMBER0='.1.
'&AMT='.$total;
// obtém o token
$paypal= new PayPalFacade;
$httpresult = $paypal->PPHttpPost('SetExpressCheckout', $padata,
$ini['username'], $ini['password']);
}
?>
30. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #30
Facade
<?php
class PaymentFacade
{
public function addItem($desc, $qtde, $preco)
{
//...
}
public function setCustomer($nome, $ender, $cidade)
{
//...
}
public function setPaymentType($type)
{
//...
}
public function process()
{
//...
}
}
?>
Pode ser resolvido
com outros
padrões também
31. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #31
Adapter
●
Favorece o isolamento e a manutenção;
●
Converte a interface de uma classe em outra;
●
Também conhecido como Wrapper:
– Object Wrapper: Encapsula adaptado por composição;
– Class Wrapper: Adapta interface por herança.
32. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #32
Adapter
<?php
class MailerAdapter
{
private $pm;
public function __construct()
{
$this->pm = new PHPMailer;
$this->pm-> CharSet = 'utf-8';
}
public function setFrom($from, $name)
{
$this->pm-> From = $from;
$this->pm-> FromName = $name;
}
public function setTextBody($body)
{
$this->pm-> Body = $body;
$this->pm-> IsHTML(false);
}
Wrapper por
Composição
33. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #33
Adapter
<?php
require_once 'PHPMailer.php';
require_once 'classes/MailerAdapter.php';
$mail = new MailerAdapter;
$mail->setUseSmtp();
$mail->setSmtpHost('smtp.gmail.com', 465);
$mail->setSmtpUser('pablo@dalloglio.net', 'minhasenha');
$mail->setFrom('pablo@dalloglio.net', 'Pablo Dall Oglio');
$mail->addAddress('destinatario@gmail.com', 'Destinatário');
$mail->setSubject('Oi Cara');
$mail->setHtmlBody('<b>Isso é um <i>teste</i></b>');
$mail->send();
Melhor
interface
34. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #34
Evolução
"... the hardest is evolving reusable object-
oriented software
We touch on this a little bit in Design Patterns.
For example, factories, adapters and facades
can help when it comes to changing and
evolving a reusable library"
Erich Gamma - Gang of Four
evoluir
35. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #35
Crie a infraestrutura
●
Autenticação;
●
Permissionamento;
●
Montagem de menus;
●
Log de mudanças;
●
Log de SQL;
●
Monitoramento;
●
Estatísticas de acesso;
●
Comunicação;
●
Notificações;
●
Compartilhamento de documentos.
Facilita o
trabalho em equipe
36. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #36
Crie configs
●
Ex: Acima de 10% de desconto do valor total da venda,
deve ser autorizados pelo setor comercial;
●
3 tentativas é o limite de acesso a uma conta até que ela
seja automaticamente bloqueada;
●
20 compras é o mínimo para ser considerado cliente VIP;
●
10% de desconto é o limite para compras a prazo.
ApplicationConfig::getValue('desconto_maximo');
Usar cache
37. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #37
Ram sessions
●
Pros: Acesso mais rápido;
●
Cons: Reiniciou, perdeu.
mkdir /var/lib/ramdisk
chmod 777 /var/lib/ramdisk
mount -t tmpfs -o size=256M tmpfs
/var/lib/ramdisk/
echo "tmpfs /var/lib/ramdisk tmpfs size=256M,atime
0 0" >> /etc/fstab
vim /etc/php5/apache2/php.ini
session.save_path = "/var/lib/ramdisk/"
38. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #38
Block sessions
●
Início: session_start() executa fopen(), lê decodifica
($_SESSION);
●
Arquivo fica em lock até o final (evitar lost updates).
●
Fim: Shutdown ou session_write_close() codifica
$_SESSION e grava no arquivo;
Ex: Front
Controller
39. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #39
Redis handler
●
Pros: Non-blocking sessions, maior escalabilidade;
●
Cons: Mais lenta.
apt-get install redis-server php5-redis
sudo vim /etc/redis/redis.conf
bind localhost
requirepass yourpasswordhere
vim /etc/php5/apache2/php.ini
session.save_handler = redis // antes files
session.save_path = "tcp://localhost:6379?
auth=yourpasswordhere"
40. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #40
Custom handler
●
Pros: Maior nível de refinamento, encrypted sessions;
●
Cons: Você gerencia.
<?php
class MySessionHandler implements SessionHandlerInterface
{
public function open ( $save_path, $name ) // session_start
public function read ( $sid ) // depois do start
public function close ( void ) // shutddown, write close
public function write ( $sid, $data ) // antes do close
public function destroy ( $sid )
public function gc ( $maxlifetime )
}
$handler = new MySessionHandler();
session_set_save_handler($handler, true);
41. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #41
Proteja as sessions
●
hijack = hacker adivinha ou rouba o sessionid, e cria um
cookie ou aplica o sessionid na URL para sequestrar a
sessão, acessando conteúdo privilegiado;
●
fixation = similar, o hacker cria a sessão, e envia a URL com
o sessionid para a vítima, que loga usando aquela sessão;
●
php.ini:
– session.use_only_cookies = 1; // não deixa o sessionid
ser lido a partir da URL, evita fixation;
– session.cookie_httponly = 1; // diz para o browser não
deixar scripts acessarem o cookie da sessão;
– PHPSESSID: Alterar nome para dificultar hijack;
– session_regenerate_id(): Dificultar hijack;
– Use HTTPS durante a transmissão.
42. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #42
Cache transparente
Poupa Requests para o Banco de dados (APC, Redis):
class Disciplina extends TRecord
{
const TABLENAME = 'disciplina';
const PRIMARYKEY = 'id';
const IDPOLICY = 'serial';
const CACHECONTROL = 'Cache-Control';
// ...
}
$turma = new Turma(10);
print $turma->disciplina->nome;
print $turma->disciplina->curso->nome;
foreach ($turma->getMatriculas() as $matricula)
{
print $matricula->aluno->nome;
print $matricula->aluno->cidade->nome;
print $matricula->aluno->cidade->estado->nome;
}
Lazy loading
43. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #43
Mais segurança
●
Essa vou deixar para o Galvão:
– Controle o input:
●
(XSS/filter_var/strip_tags/htmlspecialchars)
– Escape o output
●
Htmlentities
– Evasive (DDOS)
– Prepared Statements transparente
44. Adianti Solutions Ltda © Pablo Dall'Oglio Construindo ERP's com PHP #44
Obrigado
●
Contato:
– pablo.blog.br
– adianti.com.br
– @pablodalloglio
– @adiantisolution
●
Não esquecer de falar do Sorteio!