SlideShare uma empresa Scribd logo
1 de 44
Programando para programadores 
Desafios na evolução de um Framework 
Pablo Dall'Oglio 
@pablodalloglio fb/pablodalloglio
Meu caminho 
● Clipper (1994-1998): comercial, bibliotecas, funções; 
● Delphi (1998-1999): automação, componentes; 
● PHP (2000): SAGU (php+html+sql); 
● PHP-GTK(2001): PHP só com classes; 
● Agata Report (2001-2006); 
● Gnuteca (2002): PHP Web com classes; 
● PHP-GTK: Criando Aplicações Gráficas com PHP (2004); 
● Design Patterns (2004): Unisinos; 
● Core (2006): Primeira experiência com Framework MVC; 
● PHP: Programando com Orientação a Objetos (2007); 
● Mestrado em Engenharia de Software (2008, 2009); 
● Criando Relatórios com PHP (2011); 
● Adianti Framework para PHP (2012). 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #2
Introdução 
● Software como aplicação (final): 
– Atende os requisitos? Funciona bem? 
– Como é a usabilidade? Como é o desempenho? 
● Software como framework (meio): 
– Segue o padrão de código X? O de arquitetura Y? 
– Como é a interoperabilidade? E o aprendizado? 
● Desafios: 
– Atender padrões globais; 
– Facilidade no aprendizado; 
– Evolução tecnológica. 
Vamos compartilhar 
algumas 
experiências 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #3
Framework 
Experiências com o Adianti Framework: 
● Primeira geração em 2006; 
● Versão atual iniciou ~2008; 
● Lançado oficialmente em 2012; 
● Focado em Business apps. 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #4
#Go Horse 1 
<?php 
// configuração 
$conn = pg_connect("host=localhost port=5432 dbname=exemplos..."); 
// query 
$query = 'SELECT id, nome, endereco FROM cliente WHERE id not in (...)'; 
// resultados 
$result = pg_query($conn, $query); 
if ($result) 
{ 
Apresentação 
// apresentação 
echo '<table border="1">'; 
while ($row = pg_fetch_assoc($result)) 
{ 
echo '<tr>'; 
echo '<td>' . $row['id'] . '</td>'; 
echo '<td>' . $row['nome'] . '</td>'; 
echo '<td>' . $row['endereco'] . '</td>'; 
echo '</tr>'; 
} 
echo '</table>'; 
} 
pg_close($conn); 
Configuração 
Business rule? 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #5
Componentes 
Componentes de interface. 
$this->datagrid = new TDataGrid; 
$code = new TDataGridColumn('code', ...); 
$name = new TDataGridColumn('name', ...); 
$this->datagrid->addColumn($code); 
$this->datagrid->addColumn($name); 
$act1 = new TDataGridAction(array($this, 'onView')); 
$act1->setLabel('View name'); 
$act1->setImage('bs:search blue'); 
$act1->setField('name'); 
$act_group = new TDataGridActionGroup('Actions', 'bs:th'); 
$act_group->addHeader('Available Options'); 
$act_group->addAction($act1); 
$act_group->addAction($act2); 
$this->datagrid->addActionGroup($act_group); 
Abstrair a tecnologia 
Solução em alto nível 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #6
Componentes 
Seleção de valores 
class FormDBAutoSelectionView ... 
{ 
private $form; 
function __construct() 
{ 
parent::__construct(); 
$this->form = new TForm; 
$notebook->appendPage('Automatic selection', $this->form); 
$radio = new TDBRadioGroup('radio','samples','Category', ...); 
$check = new TDBCheckGroup('check','samples','Category',...); 
$combo = new TDBCombo('combo', 'samples', 'Category', ...); 
$select= new TDBSelect('select', 'samples', 'Category', ...); 
$search= new TDBMultiSearch('search','samples','Category', ...); 
$search->setMinLength(3); 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #7
Melhorias estruturais 
1.0.0 própria 
1.0.1 jQuery 
1.0.3 bootstrap 2 
Geração 1: Bootstrap 2 
Geração 2: Bootstrap 3 
class TMessage 
{ 
private $id; 
private $action; 
public function __construct($type, ...) 
{ 
$this->id = uniqid(); 
$modal_wrapper = new TElement('div'); 
$modal_wrapper->{'class'} = 'modal'; 
$modal_wrapper->{'id'} = $this->id; 
$modal_dialog = new TElement('div'); 
$modal_dialog->{'class'} = 'modal-dialog'; 
$modal_content = new TElement('div'); 
$modal_content->{'class'} = 'modal-content'; 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #8
Componentes 
Estrutura de um componente 
class TAccordion extends TElement 
{ 
public function __construct() 
{ 
parent::__construct('div'); 
$this->id = 'taccordion_' . uniqid(); 
} 
public function appendPage($title, $object) 
public function outroMetodo($title, $object) 
public function show() 
{ 
$title = new TElement('h3'); 
$content = new TElement('div'); 
parent::add($title); 
parent::add($content); 
parent::show(); 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #9 
} 
Estrutura para 
Extensibilidade 
app/lib
Estilização 
Customização de estilo: 
$this->datagrid = new TQuickGrid; 
$this->datagrid->class = 'customized-table'; 
parent::include_css('/.../include/custom-table.css'); 
$this->form = new TQuickForm; 
$this->form->style = 'width: 500px'; 
$this->form->class = 'tform'; 
$bt = new TButton('bt'); 
$bt->setLabel('Warning'); 
$bt->class = 'btn btn-warning btn-sm'; 
Descolamento 
entre dados, 
estrutura 
e estilização 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #10
Templates 
Interfaces muito específicas (menor reuso): 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #11
Templates 
Templates próprios 
class ProductCatalogView extends TPage 
{ 
public function __construct() 
{ 
Estrutura 
parent::__construct(); 
$this->html = new THtmlRenderer('app/.../catalog.html'); 
TPage::include_css('app/resources/catalog.css'); 
Estilo 
$replace = array(); 
$this->html->enableSection('main', $replace); 
$replace_detail[] = $product->toArray(); 
$replace_detail[] = $product->toArray(); 
$this->html->enableSection('products', $replace_detail, TRUE); 
parent::add($this->html); 
} 
Conteúdo 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #12
Desafios da evolução 
● Aderência à padrões da comunidade (Namespaces); 
● Acrescentar novos componentes de Interface; 
● Melhorar componentes existentes (+features); 
● Melhorar visual padrão, permitir customização; 
● Melhorar a estrutura de diretórios; 
● Substituir tecnologia inerente (jQuery, Bootstrap); 
● Agregar tecnologia (Font Awesome); 
● Tudo continuar funcionando; 
● Projetos grandes sendo desenvolvidos. 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #13
Estrutura de diretórios 
Isolamento entre app (user) e lib (framework, third parts). 
A carga das classes do 
FW é com ele mesmo. 
Onde geralmente 
ocorrem as mudanças 
globais em migrações 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #14
Aderência a padrões 
Namespaces 
Utilização de class_alias() para compatibilidade 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #15
Novos componentes 
● Release 1.0.1 
– TSpinner, TSlider 
● Release 1.0.2 
– TTreeview 
● Release 1.0.3 
– TSortList 
– TSelect 
● Release 2.0 
Sem 
Traumas! 
– TMultiSearch, T...ActionGroup 
– TExpander, TInputDialog, TColor 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #16
Novas features 
● Release 1.0.1 
– Edição inline (jquery.editinplace.js) 
– setExitAction (+ método) 
● Release 1.0.2 
Migration: 
Acréscimos, 
substituições 
em /lib 
– TEntry::setNumericMask (jquery.maskedinput.js) 
● Release 1.0.3 
– Nova TFile (TFile.php, tfile.js, tfile.css, same interface); 
● Release 2.0 
– Datagrid popover (jquery → bootstrap, libraries.html) 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #17
Bibliotecas utilizadas 
<!-- Third part libraries required by Adianti Framework --> 
<script src="lib/jquery/jquery.min.js"></script> 
<script src="lib/bootstrap/js/bootstrap.min.js"></script> 
<script src="lib/bootstrap/js/bootstrap-colorpicker.min.js"></script> 
<script src="lib/jquery/jquery-ui.min.js"></script> 
<script src="lib/jquery/jquery.blockUI.min.js"></script> 
<!-- Adianti Framework core and components --> 
<script src="lib/adianti/include/adianti.min.js"></script> 
<script src="lib/adianti/include/components.min.js"></script> 
<!-- Application custom Javascript (Optional) --> 
<script src="app/lib/include/application.js"></script> 
<!-- Third part CSS required by Adianti Framework --> 
<link href="lib/jquery/jquery-ui.min.css"/> 
<link href="lib/bootstrap/css/bootstrap.min.css"/> 
<link href="lib/font-awesome/css/font-awesome.min.css"/> 
<!-- Adianti Framework Components CSS --> 
<link href="lib/adianti/include/adianti.min.css"/> 
<link href="lib/adianti/include/components.css"/> 
<!-- Application custom CSS --> 
<link href="app/templates/{template}/application.css"/> 
Bootstrap 
Dialogs, buttons, 
dropdown, menubar, 
tooltip, color picker, 
date picker, multisearch 
libraries.html 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #18
#Go Horse 2 
class ContaReceber 
{ 
function inserir($id, $a, $b, $c) { 
$sql = "INSERT INTO conta_receber..."; 
// exec $sql; 
} 
function listar() { 
$sql = "SELECT * FROM conta_receber"; 
// exec $sql 
} 
function getContasEmAberto() { 
$sql = "SELECT id, sum(valor) 
Começou a separar 
FROM contas_receber cr, lancamentos l 
WHERE l.conta_id = cr.id 
GROUP BY 1 HAVING sum(valor) >1”; 
} 
function getContasEmAtraso() { 
$sql = "SELECT ... 
... 
WHERE dt_vencimento <= date(now())"; 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #19 
} 
Lógicas complexas 
extensas em SQL 
Código reflexo do BD
#Go Horse SP 
DROP PROCEDURE IF EXISTS `VALIDAVENDA`; 
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; 
UPDATE CONTAS_RECEBER SET CONTAS_RECEBER.STATUS = "Cancelado" 
WHERE CONTAS_RECEBER.COD_VENDA = ICODVENDA; 
WHILE @COD_TITULO IS NOT NULL DO 
DELETE FROM CR_CAIXA WHERE CR_CAIXA.COD_TITULO = @COD_TITULO; 
END WHILE; 
END IF; 
Como chamo aquela SP do formulário? 
END; 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #20
Orientação a modelos 
Aplicação orientada à SQL (BAD) 
● Inserir autor em livro 
INSERT INTO autor_livro (autor_id, livro_id) 
VALUES ('$autor_id', '$livro_id'); 
● Retornar os itens da Nota Fiscal 
SELECT * FROM nf, itens 
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 
à relações simples 
chaves entre tabelas 
Ver 10 piores SQL 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #21
Orientação a modelos 
Aplicação orientada ao domínio (GOOD) 
XMI → {PHP, SQL} 
Utilização de 
relações 
mais complexas. 
Modelo relacional 
é consequência 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #22
Orientação a modelos 
Exemplo de implementação 
class Filme extends TRecord 
{ 
public function get_genero() { 
if (empty($this->genero)) { 
Lazy Load 
$this->genero = new Genero( $this->genero_id ); 
} 
return $this->genero; 
} 
public function addAtor( Ator $object ) { 
$this->atores[] = $object; 
} 
public function getAtores() { 
return $this->atores; 
} 
public function load($id) { 
$this->criticas = parent::loadComposite('Critica', ...); 
$this->atores = parent::loadAggregate('Ator', ...); 
return parent::load($id); 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #23 
} 
Relações mais 
complexas, é 
preciso treinar... 
Métodos auxiliares
Orientação a modelos 
Exemplo de utilização 
// carrega o filme 
$filme = new Filme(5); 
print $filme->distribuidor->nome; 
print $filme->genero->nome; 
// carrega o filme 
$filme = new Filme(5); 
foreach ($filme->getAtores() as $ator) 
{ 
print $ator->nome; 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #24 
} 
// adiciona o ator 
$ator = new Ator(10); 
$filme->addAtor( $ator ); 
$filme->store(); 
LEGIBILIDADE 
Lazy Load MAIOR 
Agregação
Orientação a modelos 
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); 
foreach ($nf->getItems() as $item) { 
print $item->produto->descricao; 
} 
● Percorrer dados relacionados 
NAVEGABILIDADE 
entre relações 
$turma = new Turma(10); 
foreach ($turma->getMatriculas() as $matricula) { 
print $matricula->aluno->nome; 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #25
Persistência 
Armazenar um novo objeto (INSERT). 
//... 
TTransaction::open('samples'); // abre uma transação 
$object = new Pessoa; 
$object->name = 'Maria da Silva'; 
$object->address = 'Rua da Conceicao'; 
$object->phone = '(51) 8111-2222'; 
$object->birthdate = '2013-02-15'; 
$object->status = 'S'; 
$object->email = 'maria@email.com'; 
$object->gender = 'M'; 
$object->store(); // armazena o objeto 
TTransaction::close(); // fecha a transação. 
//... 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #26
Persistência 
Alterar um objeto já existente (UPDATE). 
//... 
TTransaction::open('samples'); // abre uma transação 
$objeto = new Customer; // instancia o cliente 
$customer= $objeto->load(31); // carrega o cliente 31 
if ($customer) // se existe 
{ 
$customer->phone = '51 8111-3333'; // muda o fone 
$customer->store(); // armazena o objeto 
} 
new TMessage('info', 'Objeto atualizado'); 
TTransaction::close(); // fecha a transação. 
//... 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #27
Persistência 
Manipular um conjunto de objetos conforme um filtro. 
//... 
TTransaction::open('samples'); // abre uma transação 
$repository = new TRepository('Customer'); 
$customers = $repository->where('gender', '=', 'M') 
->where('name', 'like', 'A%') 
->load(); 
foreach ($customers as $customer) 
{ 
$customer->phone = '84 '.substr($customer->phone, 3); 
$customer->store(); 
} 
Active Record 
TTransaction::close(); // fecha a transação. 
//... 
Repository 
Pattern 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #28
Object caching 
Melhorias para a versão 2.0: 
● Cache Service 
class Customer extends TRecord 
{ 
1/3 tempo na matrícula 
const TABLENAME = 'customer'; 
const PRIMARYKEY = 'id'; 
const IDPOLICY = 'max'; // {max, serial} 
const CACHECONTROL = 'Cache-Control-Class'; 
// ... 
} 
● Utilizado em: 
Grandes ganhos de 
Performance 
Deve implementar 
classe específica 
– Carregar objeto, Salvar objeto, Excluir objeto; 
– Carregar coleções, Excluir coleções; 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #29
Object caching 
Implementação de cache usando APC: 
class TAPCache implements AdiantiRegistryInterface 
{ 
public static function enabled() { 
return extension_loaded('apc'); 
} 
public static function setValue($key, $value) { 
return apc_store($key, serialize($value)); 
} 
public static function getValue($key) { 
return unserialize(apc_fetch($key)); 
} 
public static function delValue($key) { 
return apc_delete($key); 
} 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #30
Prepared Statements 
Melhorias para a versão 2.0: 
● Prepared Statements transparente: 
– Habilitar/desabilitar por transação (performance); 
$data = $this->form->getData(); 
Query Object pattern 
TTransaction::open('samples'); 
$criteria = new TCriteria; 
$criteria->add(new TFilter('gender', '=', $data->gender)); 
$criteria->add(new TFilter('age', '>', $data->age)); 
$criteria->add(new TFilter('haircolor', '>', $data->haircolor)); 
$repository = new TRepository('Customer'); 
$customers = $repository->load($criteria); 
TTransaction::close(); 
Prepared 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #31
Prepared Statements 
Como o Prepared é processado: 
TTransaction::log($sql->getInstruction()); 
$dbinfo = TTransaction::getDatabaseInfo(); 
if (isset($dbinfo['prep']) AND $dbinfo['prep'] == '1') 
{ 
Com prepared 
$result = $conn->prepare($sql->getInstruction(TRUE), ...); 
$result-> execute( $sql->getPreparedVars() ); 
} 
else { 
Sem prepared 
$result = $conn-> query($sql->getInstruction()); 
} 
if ( $cache = $this->getCacheControl() ) { 
Atualiza cache 
$record_key = $class . '['. $this->$pk . ']'; 
if ($cache::setValue( $record_key, $this->toArray() )) { 
TTransaction::log($record_key . ' stored in cache'); 
} 
} 
return $result; 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #32
Novas restrições 
● Release 1.0.2 
– TForm::addField() 2 campos mesmo nome; 
– TForm::addField() só aceita AdiantiWidgetInterface. 
class TForm 
{ 
public function addField( AdiantiWidgetInterface $field ) 
{ 
$name = $field->getName(); 
if (isset($this->fields[$name])) 
{ 
throw new Exception(TAdiantiCoreTranslator::translate('You 
have already added a field called "^1" inside the form', $name)); 
} 
$this->fields[$name] = $field; 
$field->setFormName($this->name); 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #33 
} 
Resiliência 
1o programador = instrução 
2o programador = exceção
Novas restrições 
● Release 1.0.3 
– TRecord::addAttribute() não pode ter atributo data; 
– setLogger() sem transação ativa lança exceção; 
final class TTransaction 
{ 
public static function setLogger( TLogger $logger) 
{ 
if (isset(self::$conn[self::$counter])) 
{ 
self::$logger[self::$counter] = $logger; 
} 
else 
{ 
Não esperar que 
as coisas 
estejam certas 
throw new Exception(TAdiantiCoreTranslator::translate('No 
active transactions') . ': ' . __METHOD__); 
} 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #34 
} 
Controle
Novas restrições 
● Release 2.0 (PSR-3) 
– TTransaction implements LoggerAwareInterface; 
– TLogger's implements LoggerInterface. 
final class TTransaction implements LoggerAwareInterface 
{ 
Ciência 
public static function setLogger( LoggerInterface $logger) 
{ 
if (isset(self::$conn[self::$counter])) 
{ 
self::$logger[self::$counter] = $logger; 
} 
else 
{ 
throw new Exception(TAdiantiCoreTranslator::translate('No 
active transactions') . ': ' . __METHOD__); 
} 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #35 
} 
Antes, TLogger
E o que mais? 
● Práticas! 
– Onde colocar tal método? M,V, ou C? Qual das M? 
– Nunca a Model deve dar TMessage; 
– Model não deve dar return em falha, só throw; 
– Nunca abrir transaction na model (Model agnóstica); 
– Catch sempre na controller; 
– Transactions somente na controller; 
– Usar getByAlgumaCoisa(). Ex: Turma::getByCodigo(); 
– Objetos de negócio sempre em Português (Aluno); 
– Métodos-ação imprimeAluno(), geraCertificado(). 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #36
Ferramentas profissionais
Studio Pro 
<?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) 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #38 
} ?> 
XMI 
SQL 
PHP 
Modelo 
Astah 
StarUML
Studio Pro 
● Se o modelo for feito antes, facilita tudo; 
● Relações podem ser definidas por wizards também. 
<?php 
// load customer 
$obj = new Customer(5); 
print $obj->city->name; 
print $obj->category->name; 
// percorre contatos 
foreach ($obj->getContacts() as $contact) 
{ 
$contact->value = '9'.$contact->value; 
$contact->store(); 
print $contact->type . '-' . $contact->value; 
} 
foreach ($obj->getSkills() as $skill) 
{ 
print $skill->name; 
} 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #39
Studio Form Designer 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #40
Studio Form Designer 
class TestView extends TPage 
{ 
private $form; 
function __construct() 
{ 
parent::__construct(); 
$this->form = new TForm; 
try { 
Wrapper 
$ui = new TUIBuilder(500,300); 
$ui->setController($this); 
$ui->setForm($this->form); 
$ui->parseFile('app/forms/sample.form.xml'); 
$this->form->add($ui); 
$this->form->setFields($ui->getFields()); 
} 
catch (Exception $e) { 
new TMessage('error', $e->getMessage()); 
} 
parent::add($this->form); 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #41
Studio PDF Designer 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #42
Studio PDF Designer 
class PDFDesignNFEView extends TPage 
{ 
function onGenerate() 
{ 
Wrapper 
try 
{ 
$designer = new TPDFDesigner; 
$designer->fromXml('app/reports/nfe.pdf.xml'); 
$designer->generate(); 
$designer->SetFont('Arial', 'B', 8); 
$designer->setFontColorRGB( '#4C4491' ); 
$designer->writeAtAnchor('bairro', 'Centro'); 
$designer->writeAtAnchor('municipio', 'Cidade teste'); 
$designer->writeAtAnchor('fone', '(11) 1234-5678'); 
$designer->gotoAnchorXY('details'); 
$designer->SetFont('Arial', '', 8); 
$designer->Cell( 62, 10, '12121212', 1, 0, 'C'); 
$designer->Cell(140, 10, utf8_decode('Guaraná'), 1, 0, 'L'); 
} 
//... 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #43
Obrigado 
● Adianti Framework: 
– www.adianti.com.br/framework 
● Contato: 
– www.dalloglio.net 
– www.adianti.com.br 
– @pablodalloglio 
– @adiantisolution 
● Não esquecer de falar do Sorteio! 
Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #44

Mais conteúdo relacionado

Mais procurados

PHP: Programando com orientação a Objetos
PHP: Programando com orientação a ObjetosPHP: Programando com orientação a Objetos
PHP: Programando com orientação a Objetos
Pablo Dall'Oglio
 
Serversidephp pptx2-120418140114-phpapp01
Serversidephp pptx2-120418140114-phpapp01Serversidephp pptx2-120418140114-phpapp01
Serversidephp pptx2-120418140114-phpapp01
joaocarlobarros
 
Técnicas de Refactorización (EN ESPANOL)
Técnicas de Refactorización (EN ESPANOL)Técnicas de Refactorización (EN ESPANOL)
Técnicas de Refactorización (EN ESPANOL)
Rodrigo Branas
 

Mais procurados (20)

PHP: Programando com orientação a Objetos
PHP: Programando com orientação a ObjetosPHP: Programando com orientação a Objetos
PHP: Programando com orientação a Objetos
 
Design for change: Fatores que influenciam na longevidade de um Software PHP
Design for change: Fatores que influenciam na longevidade de um Software PHPDesign for change: Fatores que influenciam na longevidade de um Software PHP
Design for change: Fatores que influenciam na longevidade de um Software PHP
 
Fatores que influenciam na longevidade de um Software
Fatores que influenciam na longevidade de um SoftwareFatores que influenciam na longevidade de um Software
Fatores que influenciam na longevidade de um Software
 
Solid
SolidSolid
Solid
 
Django
DjangoDjango
Django
 
PHP e Redis
PHP e RedisPHP e Redis
PHP e Redis
 
Domain Driven Design PHP TDC2014
Domain Driven Design PHP TDC2014Domain Driven Design PHP TDC2014
Domain Driven Design PHP TDC2014
 
Programação orientada a objetos em delphi
Programação orientada a objetos em delphiProgramação orientada a objetos em delphi
Programação orientada a objetos em delphi
 
Treinamento Básico de Django
Treinamento Básico de DjangoTreinamento Básico de Django
Treinamento Básico de Django
 
Clean Code e Object Calisthenics - Aplicados no PHP
Clean Code e Object Calisthenics - Aplicados no PHPClean Code e Object Calisthenics - Aplicados no PHP
Clean Code e Object Calisthenics - Aplicados no PHP
 
Serversidephp pptx2-120418140114-phpapp01
Serversidephp pptx2-120418140114-phpapp01Serversidephp pptx2-120418140114-phpapp01
Serversidephp pptx2-120418140114-phpapp01
 
Programação Orientada por Objectos - Aula 2
Programação Orientada por Objectos - Aula 2Programação Orientada por Objectos - Aula 2
Programação Orientada por Objectos - Aula 2
 
Programação Orientada por Objectos - Aula 1
Programação Orientada por Objectos - Aula 1Programação Orientada por Objectos - Aula 1
Programação Orientada por Objectos - Aula 1
 
Trabalhando com as views do Web2Py
Trabalhando com as views do Web2PyTrabalhando com as views do Web2Py
Trabalhando com as views do Web2Py
 
Web2py: Desenvolvimento Ágil de Aplicações Web com Python
Web2py: Desenvolvimento Ágil de Aplicações Web com PythonWeb2py: Desenvolvimento Ágil de Aplicações Web com Python
Web2py: Desenvolvimento Ágil de Aplicações Web com Python
 
Técnicas de Refactorización (EN ESPANOL)
Técnicas de Refactorización (EN ESPANOL)Técnicas de Refactorización (EN ESPANOL)
Técnicas de Refactorización (EN ESPANOL)
 
Java Web, o Tutorial
Java Web, o TutorialJava Web, o Tutorial
Java Web, o Tutorial
 
Django Módulo Básico Parte I - Desenvolvimento de uma aplicação Web
Django Módulo Básico Parte I - Desenvolvimento de uma aplicação WebDjango Módulo Básico Parte I - Desenvolvimento de uma aplicação Web
Django Módulo Básico Parte I - Desenvolvimento de uma aplicação Web
 
Mvc delphi
Mvc delphiMvc delphi
Mvc delphi
 
Java aula 04
Java aula 04Java aula 04
Java aula 04
 

Semelhante a Programando para programadores: Desafios na evolução de um Framework

Drupal 7 Direto das Trincheiras
Drupal 7  Direto das TrincheirasDrupal 7  Direto das Trincheiras
Drupal 7 Direto das Trincheiras
Rafael Caceres
 

Semelhante a Programando para programadores: Desafios na evolução de um Framework (20)

Desenvolvimento ágil com Kohana framework
Desenvolvimento ágil com Kohana frameworkDesenvolvimento ágil com Kohana framework
Desenvolvimento ágil com Kohana framework
 
Aplicações rápidas para a Web com Django
Aplicações rápidas para a Web com DjangoAplicações rápidas para a Web com Django
Aplicações rápidas para a Web com Django
 
Desenvolvendo aplicações web com o framework cakephp
Desenvolvendo aplicações web com o framework cakephpDesenvolvendo aplicações web com o framework cakephp
Desenvolvendo aplicações web com o framework cakephp
 
Aplicacoes Rapidas Para Web Com Django
Aplicacoes Rapidas Para Web Com DjangoAplicacoes Rapidas Para Web Com Django
Aplicacoes Rapidas Para Web Com Django
 
Lampada Php Conference Brasil 2007 Palestra
Lampada Php Conference Brasil 2007 PalestraLampada Php Conference Brasil 2007 Palestra
Lampada Php Conference Brasil 2007 Palestra
 
Zend Framework
Zend FrameworkZend Framework
Zend Framework
 
Zend Framework
Zend FrameworkZend Framework
Zend Framework
 
Zend Framework 1.11
Zend Framework 1.11Zend Framework 1.11
Zend Framework 1.11
 
Drupal 7 Direto das Trincheiras
Drupal 7  Direto das TrincheirasDrupal 7  Direto das Trincheiras
Drupal 7 Direto das Trincheiras
 
Django: Desenvolvendo uma aplicação web em minutos
Django: Desenvolvendo uma aplicação web em minutosDjango: Desenvolvendo uma aplicação web em minutos
Django: Desenvolvendo uma aplicação web em minutos
 
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
Desenvolvimento de Aplicações para o Google App Engine (CPBR5)
 
Desenvolvimento de aplicações para o Google App Engine
Desenvolvimento de aplicações para o Google App EngineDesenvolvimento de aplicações para o Google App Engine
Desenvolvimento de aplicações para o Google App Engine
 
Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOL
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017
 
Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Introdução ao Zend Framework 2
Introdução ao Zend Framework 2
 
Meu projeto final - Neobase 2.0
Meu projeto final - Neobase 2.0Meu projeto final - Neobase 2.0
Meu projeto final - Neobase 2.0
 
Analise frameworks php
Analise frameworks phpAnalise frameworks php
Analise frameworks php
 
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
 
Desenvolvendo com Dojo Toolkit
Desenvolvendo com Dojo ToolkitDesenvolvendo com Dojo Toolkit
Desenvolvendo com Dojo Toolkit
 

Último

Último (8)

ATIVIDADE 1 - GESTÃO DE PESSOAS E DESENVOLVIMENTO DE EQUIPES - 52_2024.docx
ATIVIDADE 1 - GESTÃO DE PESSOAS E DESENVOLVIMENTO DE EQUIPES - 52_2024.docxATIVIDADE 1 - GESTÃO DE PESSOAS E DESENVOLVIMENTO DE EQUIPES - 52_2024.docx
ATIVIDADE 1 - GESTÃO DE PESSOAS E DESENVOLVIMENTO DE EQUIPES - 52_2024.docx
 
Entrevistas, artigos, livros & citações de Paulo Pagliusi
Entrevistas, artigos, livros & citações de Paulo PagliusiEntrevistas, artigos, livros & citações de Paulo Pagliusi
Entrevistas, artigos, livros & citações de Paulo Pagliusi
 
ATIVIDADE 1 - CÁLCULO DIFERENCIAL E INTEGRAL II - 52_2024.docx
ATIVIDADE 1 - CÁLCULO DIFERENCIAL E INTEGRAL II - 52_2024.docxATIVIDADE 1 - CÁLCULO DIFERENCIAL E INTEGRAL II - 52_2024.docx
ATIVIDADE 1 - CÁLCULO DIFERENCIAL E INTEGRAL II - 52_2024.docx
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
 
Aula 01 - Introducao a Processamento de Frutos e Hortalicas.pdf
Aula 01 - Introducao a Processamento de Frutos e Hortalicas.pdfAula 01 - Introducao a Processamento de Frutos e Hortalicas.pdf
Aula 01 - Introducao a Processamento de Frutos e Hortalicas.pdf
 
COI CENTRO DE OPERAÇÕES INDUSTRIAIS NAS USINAS
COI CENTRO DE OPERAÇÕES INDUSTRIAIS NAS USINASCOI CENTRO DE OPERAÇÕES INDUSTRIAIS NAS USINAS
COI CENTRO DE OPERAÇÕES INDUSTRIAIS NAS USINAS
 
EAD Curso - CIÊNCIA DE DADOS NA INDÚSTTRIA
EAD Curso - CIÊNCIA DE DADOS NA INDÚSTTRIAEAD Curso - CIÊNCIA DE DADOS NA INDÚSTTRIA
EAD Curso - CIÊNCIA DE DADOS NA INDÚSTTRIA
 
Palestras sobre Cibersegurança em Eventos - Paulo Pagliusi
Palestras sobre Cibersegurança em Eventos - Paulo PagliusiPalestras sobre Cibersegurança em Eventos - Paulo Pagliusi
Palestras sobre Cibersegurança em Eventos - Paulo Pagliusi
 

Programando para programadores: Desafios na evolução de um Framework

  • 1. Programando para programadores Desafios na evolução de um Framework Pablo Dall'Oglio @pablodalloglio fb/pablodalloglio
  • 2. Meu caminho ● Clipper (1994-1998): comercial, bibliotecas, funções; ● Delphi (1998-1999): automação, componentes; ● PHP (2000): SAGU (php+html+sql); ● PHP-GTK(2001): PHP só com classes; ● Agata Report (2001-2006); ● Gnuteca (2002): PHP Web com classes; ● PHP-GTK: Criando Aplicações Gráficas com PHP (2004); ● Design Patterns (2004): Unisinos; ● Core (2006): Primeira experiência com Framework MVC; ● PHP: Programando com Orientação a Objetos (2007); ● Mestrado em Engenharia de Software (2008, 2009); ● Criando Relatórios com PHP (2011); ● Adianti Framework para PHP (2012). Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #2
  • 3. Introdução ● Software como aplicação (final): – Atende os requisitos? Funciona bem? – Como é a usabilidade? Como é o desempenho? ● Software como framework (meio): – Segue o padrão de código X? O de arquitetura Y? – Como é a interoperabilidade? E o aprendizado? ● Desafios: – Atender padrões globais; – Facilidade no aprendizado; – Evolução tecnológica. Vamos compartilhar algumas experiências Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #3
  • 4. Framework Experiências com o Adianti Framework: ● Primeira geração em 2006; ● Versão atual iniciou ~2008; ● Lançado oficialmente em 2012; ● Focado em Business apps. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #4
  • 5. #Go Horse 1 <?php // configuração $conn = pg_connect("host=localhost port=5432 dbname=exemplos..."); // query $query = 'SELECT id, nome, endereco FROM cliente WHERE id not in (...)'; // resultados $result = pg_query($conn, $query); if ($result) { Apresentação // apresentação echo '<table border="1">'; while ($row = pg_fetch_assoc($result)) { echo '<tr>'; echo '<td>' . $row['id'] . '</td>'; echo '<td>' . $row['nome'] . '</td>'; echo '<td>' . $row['endereco'] . '</td>'; echo '</tr>'; } echo '</table>'; } pg_close($conn); Configuração Business rule? Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #5
  • 6. Componentes Componentes de interface. $this->datagrid = new TDataGrid; $code = new TDataGridColumn('code', ...); $name = new TDataGridColumn('name', ...); $this->datagrid->addColumn($code); $this->datagrid->addColumn($name); $act1 = new TDataGridAction(array($this, 'onView')); $act1->setLabel('View name'); $act1->setImage('bs:search blue'); $act1->setField('name'); $act_group = new TDataGridActionGroup('Actions', 'bs:th'); $act_group->addHeader('Available Options'); $act_group->addAction($act1); $act_group->addAction($act2); $this->datagrid->addActionGroup($act_group); Abstrair a tecnologia Solução em alto nível Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #6
  • 7. Componentes Seleção de valores class FormDBAutoSelectionView ... { private $form; function __construct() { parent::__construct(); $this->form = new TForm; $notebook->appendPage('Automatic selection', $this->form); $radio = new TDBRadioGroup('radio','samples','Category', ...); $check = new TDBCheckGroup('check','samples','Category',...); $combo = new TDBCombo('combo', 'samples', 'Category', ...); $select= new TDBSelect('select', 'samples', 'Category', ...); $search= new TDBMultiSearch('search','samples','Category', ...); $search->setMinLength(3); Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #7
  • 8. Melhorias estruturais 1.0.0 própria 1.0.1 jQuery 1.0.3 bootstrap 2 Geração 1: Bootstrap 2 Geração 2: Bootstrap 3 class TMessage { private $id; private $action; public function __construct($type, ...) { $this->id = uniqid(); $modal_wrapper = new TElement('div'); $modal_wrapper->{'class'} = 'modal'; $modal_wrapper->{'id'} = $this->id; $modal_dialog = new TElement('div'); $modal_dialog->{'class'} = 'modal-dialog'; $modal_content = new TElement('div'); $modal_content->{'class'} = 'modal-content'; Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #8
  • 9. Componentes Estrutura de um componente class TAccordion extends TElement { public function __construct() { parent::__construct('div'); $this->id = 'taccordion_' . uniqid(); } public function appendPage($title, $object) public function outroMetodo($title, $object) public function show() { $title = new TElement('h3'); $content = new TElement('div'); parent::add($title); parent::add($content); parent::show(); } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #9 } Estrutura para Extensibilidade app/lib
  • 10. Estilização Customização de estilo: $this->datagrid = new TQuickGrid; $this->datagrid->class = 'customized-table'; parent::include_css('/.../include/custom-table.css'); $this->form = new TQuickForm; $this->form->style = 'width: 500px'; $this->form->class = 'tform'; $bt = new TButton('bt'); $bt->setLabel('Warning'); $bt->class = 'btn btn-warning btn-sm'; Descolamento entre dados, estrutura e estilização Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #10
  • 11. Templates Interfaces muito específicas (menor reuso): Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #11
  • 12. Templates Templates próprios class ProductCatalogView extends TPage { public function __construct() { Estrutura parent::__construct(); $this->html = new THtmlRenderer('app/.../catalog.html'); TPage::include_css('app/resources/catalog.css'); Estilo $replace = array(); $this->html->enableSection('main', $replace); $replace_detail[] = $product->toArray(); $replace_detail[] = $product->toArray(); $this->html->enableSection('products', $replace_detail, TRUE); parent::add($this->html); } Conteúdo Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #12
  • 13. Desafios da evolução ● Aderência à padrões da comunidade (Namespaces); ● Acrescentar novos componentes de Interface; ● Melhorar componentes existentes (+features); ● Melhorar visual padrão, permitir customização; ● Melhorar a estrutura de diretórios; ● Substituir tecnologia inerente (jQuery, Bootstrap); ● Agregar tecnologia (Font Awesome); ● Tudo continuar funcionando; ● Projetos grandes sendo desenvolvidos. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #13
  • 14. Estrutura de diretórios Isolamento entre app (user) e lib (framework, third parts). A carga das classes do FW é com ele mesmo. Onde geralmente ocorrem as mudanças globais em migrações Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #14
  • 15. Aderência a padrões Namespaces Utilização de class_alias() para compatibilidade Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #15
  • 16. Novos componentes ● Release 1.0.1 – TSpinner, TSlider ● Release 1.0.2 – TTreeview ● Release 1.0.3 – TSortList – TSelect ● Release 2.0 Sem Traumas! – TMultiSearch, T...ActionGroup – TExpander, TInputDialog, TColor Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #16
  • 17. Novas features ● Release 1.0.1 – Edição inline (jquery.editinplace.js) – setExitAction (+ método) ● Release 1.0.2 Migration: Acréscimos, substituições em /lib – TEntry::setNumericMask (jquery.maskedinput.js) ● Release 1.0.3 – Nova TFile (TFile.php, tfile.js, tfile.css, same interface); ● Release 2.0 – Datagrid popover (jquery → bootstrap, libraries.html) Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #17
  • 18. Bibliotecas utilizadas <!-- Third part libraries required by Adianti Framework --> <script src="lib/jquery/jquery.min.js"></script> <script src="lib/bootstrap/js/bootstrap.min.js"></script> <script src="lib/bootstrap/js/bootstrap-colorpicker.min.js"></script> <script src="lib/jquery/jquery-ui.min.js"></script> <script src="lib/jquery/jquery.blockUI.min.js"></script> <!-- Adianti Framework core and components --> <script src="lib/adianti/include/adianti.min.js"></script> <script src="lib/adianti/include/components.min.js"></script> <!-- Application custom Javascript (Optional) --> <script src="app/lib/include/application.js"></script> <!-- Third part CSS required by Adianti Framework --> <link href="lib/jquery/jquery-ui.min.css"/> <link href="lib/bootstrap/css/bootstrap.min.css"/> <link href="lib/font-awesome/css/font-awesome.min.css"/> <!-- Adianti Framework Components CSS --> <link href="lib/adianti/include/adianti.min.css"/> <link href="lib/adianti/include/components.css"/> <!-- Application custom CSS --> <link href="app/templates/{template}/application.css"/> Bootstrap Dialogs, buttons, dropdown, menubar, tooltip, color picker, date picker, multisearch libraries.html Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #18
  • 19. #Go Horse 2 class ContaReceber { function inserir($id, $a, $b, $c) { $sql = "INSERT INTO conta_receber..."; // exec $sql; } function listar() { $sql = "SELECT * FROM conta_receber"; // exec $sql } function getContasEmAberto() { $sql = "SELECT id, sum(valor) Começou a separar FROM contas_receber cr, lancamentos l WHERE l.conta_id = cr.id GROUP BY 1 HAVING sum(valor) >1”; } function getContasEmAtraso() { $sql = "SELECT ... ... WHERE dt_vencimento <= date(now())"; } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #19 } Lógicas complexas extensas em SQL Código reflexo do BD
  • 20. #Go Horse SP DROP PROCEDURE IF EXISTS `VALIDAVENDA`; 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; UPDATE CONTAS_RECEBER SET CONTAS_RECEBER.STATUS = "Cancelado" WHERE CONTAS_RECEBER.COD_VENDA = ICODVENDA; WHILE @COD_TITULO IS NOT NULL DO DELETE FROM CR_CAIXA WHERE CR_CAIXA.COD_TITULO = @COD_TITULO; END WHILE; END IF; Como chamo aquela SP do formulário? END; Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #20
  • 21. Orientação a modelos Aplicação orientada à SQL (BAD) ● Inserir autor em livro INSERT INTO autor_livro (autor_id, livro_id) VALUES ('$autor_id', '$livro_id'); ● Retornar os itens da Nota Fiscal SELECT * FROM nf, itens 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 à relações simples chaves entre tabelas Ver 10 piores SQL Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #21
  • 22. Orientação a modelos Aplicação orientada ao domínio (GOOD) XMI → {PHP, SQL} Utilização de relações mais complexas. Modelo relacional é consequência Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #22
  • 23. Orientação a modelos Exemplo de implementação class Filme extends TRecord { public function get_genero() { if (empty($this->genero)) { Lazy Load $this->genero = new Genero( $this->genero_id ); } return $this->genero; } public function addAtor( Ator $object ) { $this->atores[] = $object; } public function getAtores() { return $this->atores; } public function load($id) { $this->criticas = parent::loadComposite('Critica', ...); $this->atores = parent::loadAggregate('Ator', ...); return parent::load($id); } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #23 } Relações mais complexas, é preciso treinar... Métodos auxiliares
  • 24. Orientação a modelos Exemplo de utilização // carrega o filme $filme = new Filme(5); print $filme->distribuidor->nome; print $filme->genero->nome; // carrega o filme $filme = new Filme(5); foreach ($filme->getAtores() as $ator) { print $ator->nome; Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #24 } // adiciona o ator $ator = new Ator(10); $filme->addAtor( $ator ); $filme->store(); LEGIBILIDADE Lazy Load MAIOR Agregação
  • 25. Orientação a modelos 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); foreach ($nf->getItems() as $item) { print $item->produto->descricao; } ● Percorrer dados relacionados NAVEGABILIDADE entre relações $turma = new Turma(10); foreach ($turma->getMatriculas() as $matricula) { print $matricula->aluno->nome; } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #25
  • 26. Persistência Armazenar um novo objeto (INSERT). //... TTransaction::open('samples'); // abre uma transação $object = new Pessoa; $object->name = 'Maria da Silva'; $object->address = 'Rua da Conceicao'; $object->phone = '(51) 8111-2222'; $object->birthdate = '2013-02-15'; $object->status = 'S'; $object->email = 'maria@email.com'; $object->gender = 'M'; $object->store(); // armazena o objeto TTransaction::close(); // fecha a transação. //... Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #26
  • 27. Persistência Alterar um objeto já existente (UPDATE). //... TTransaction::open('samples'); // abre uma transação $objeto = new Customer; // instancia o cliente $customer= $objeto->load(31); // carrega o cliente 31 if ($customer) // se existe { $customer->phone = '51 8111-3333'; // muda o fone $customer->store(); // armazena o objeto } new TMessage('info', 'Objeto atualizado'); TTransaction::close(); // fecha a transação. //... Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #27
  • 28. Persistência Manipular um conjunto de objetos conforme um filtro. //... TTransaction::open('samples'); // abre uma transação $repository = new TRepository('Customer'); $customers = $repository->where('gender', '=', 'M') ->where('name', 'like', 'A%') ->load(); foreach ($customers as $customer) { $customer->phone = '84 '.substr($customer->phone, 3); $customer->store(); } Active Record TTransaction::close(); // fecha a transação. //... Repository Pattern Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #28
  • 29. Object caching Melhorias para a versão 2.0: ● Cache Service class Customer extends TRecord { 1/3 tempo na matrícula const TABLENAME = 'customer'; const PRIMARYKEY = 'id'; const IDPOLICY = 'max'; // {max, serial} const CACHECONTROL = 'Cache-Control-Class'; // ... } ● Utilizado em: Grandes ganhos de Performance Deve implementar classe específica – Carregar objeto, Salvar objeto, Excluir objeto; – Carregar coleções, Excluir coleções; Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #29
  • 30. Object caching Implementação de cache usando APC: class TAPCache implements AdiantiRegistryInterface { public static function enabled() { return extension_loaded('apc'); } public static function setValue($key, $value) { return apc_store($key, serialize($value)); } public static function getValue($key) { return unserialize(apc_fetch($key)); } public static function delValue($key) { return apc_delete($key); } } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #30
  • 31. Prepared Statements Melhorias para a versão 2.0: ● Prepared Statements transparente: – Habilitar/desabilitar por transação (performance); $data = $this->form->getData(); Query Object pattern TTransaction::open('samples'); $criteria = new TCriteria; $criteria->add(new TFilter('gender', '=', $data->gender)); $criteria->add(new TFilter('age', '>', $data->age)); $criteria->add(new TFilter('haircolor', '>', $data->haircolor)); $repository = new TRepository('Customer'); $customers = $repository->load($criteria); TTransaction::close(); Prepared Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #31
  • 32. Prepared Statements Como o Prepared é processado: TTransaction::log($sql->getInstruction()); $dbinfo = TTransaction::getDatabaseInfo(); if (isset($dbinfo['prep']) AND $dbinfo['prep'] == '1') { Com prepared $result = $conn->prepare($sql->getInstruction(TRUE), ...); $result-> execute( $sql->getPreparedVars() ); } else { Sem prepared $result = $conn-> query($sql->getInstruction()); } if ( $cache = $this->getCacheControl() ) { Atualiza cache $record_key = $class . '['. $this->$pk . ']'; if ($cache::setValue( $record_key, $this->toArray() )) { TTransaction::log($record_key . ' stored in cache'); } } return $result; Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #32
  • 33. Novas restrições ● Release 1.0.2 – TForm::addField() 2 campos mesmo nome; – TForm::addField() só aceita AdiantiWidgetInterface. class TForm { public function addField( AdiantiWidgetInterface $field ) { $name = $field->getName(); if (isset($this->fields[$name])) { throw new Exception(TAdiantiCoreTranslator::translate('You have already added a field called "^1" inside the form', $name)); } $this->fields[$name] = $field; $field->setFormName($this->name); } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #33 } Resiliência 1o programador = instrução 2o programador = exceção
  • 34. Novas restrições ● Release 1.0.3 – TRecord::addAttribute() não pode ter atributo data; – setLogger() sem transação ativa lança exceção; final class TTransaction { public static function setLogger( TLogger $logger) { if (isset(self::$conn[self::$counter])) { self::$logger[self::$counter] = $logger; } else { Não esperar que as coisas estejam certas throw new Exception(TAdiantiCoreTranslator::translate('No active transactions') . ': ' . __METHOD__); } } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #34 } Controle
  • 35. Novas restrições ● Release 2.0 (PSR-3) – TTransaction implements LoggerAwareInterface; – TLogger's implements LoggerInterface. final class TTransaction implements LoggerAwareInterface { Ciência public static function setLogger( LoggerInterface $logger) { if (isset(self::$conn[self::$counter])) { self::$logger[self::$counter] = $logger; } else { throw new Exception(TAdiantiCoreTranslator::translate('No active transactions') . ': ' . __METHOD__); } } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #35 } Antes, TLogger
  • 36. E o que mais? ● Práticas! – Onde colocar tal método? M,V, ou C? Qual das M? – Nunca a Model deve dar TMessage; – Model não deve dar return em falha, só throw; – Nunca abrir transaction na model (Model agnóstica); – Catch sempre na controller; – Transactions somente na controller; – Usar getByAlgumaCoisa(). Ex: Turma::getByCodigo(); – Objetos de negócio sempre em Português (Aluno); – Métodos-ação imprimeAluno(), geraCertificado(). Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #36
  • 38. Studio Pro <?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) Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #38 } ?> XMI SQL PHP Modelo Astah StarUML
  • 39. Studio Pro ● Se o modelo for feito antes, facilita tudo; ● Relações podem ser definidas por wizards também. <?php // load customer $obj = new Customer(5); print $obj->city->name; print $obj->category->name; // percorre contatos foreach ($obj->getContacts() as $contact) { $contact->value = '9'.$contact->value; $contact->store(); print $contact->type . '-' . $contact->value; } foreach ($obj->getSkills() as $skill) { print $skill->name; } Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #39
  • 40. Studio Form Designer Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #40
  • 41. Studio Form Designer class TestView extends TPage { private $form; function __construct() { parent::__construct(); $this->form = new TForm; try { Wrapper $ui = new TUIBuilder(500,300); $ui->setController($this); $ui->setForm($this->form); $ui->parseFile('app/forms/sample.form.xml'); $this->form->add($ui); $this->form->setFields($ui->getFields()); } catch (Exception $e) { new TMessage('error', $e->getMessage()); } parent::add($this->form); Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #41
  • 42. Studio PDF Designer Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #42
  • 43. Studio PDF Designer class PDFDesignNFEView extends TPage { function onGenerate() { Wrapper try { $designer = new TPDFDesigner; $designer->fromXml('app/reports/nfe.pdf.xml'); $designer->generate(); $designer->SetFont('Arial', 'B', 8); $designer->setFontColorRGB( '#4C4491' ); $designer->writeAtAnchor('bairro', 'Centro'); $designer->writeAtAnchor('municipio', 'Cidade teste'); $designer->writeAtAnchor('fone', '(11) 1234-5678'); $designer->gotoAnchorXY('details'); $designer->SetFont('Arial', '', 8); $designer->Cell( 62, 10, '12121212', 1, 0, 'C'); $designer->Cell(140, 10, utf8_decode('Guaraná'), 1, 0, 'L'); } //... Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #43
  • 44. Obrigado ● Adianti Framework: – www.adianti.com.br/framework ● Contato: – www.dalloglio.net – www.adianti.com.br – @pablodalloglio – @adiantisolution ● Não esquecer de falar do Sorteio! Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #44