Contenu connexe Similaire à Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks (20) Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks1. Do Clipper e Delphi ao Ruby e PHP
Antes e depois dos frameworks
Pablo Dall'Oglio
@pablodalloglio fb/pablodalloglio
5. Adianti Solutions Ltda © Pablo Dall'Oglio #5
CA-Clipper
Sobre o Clipper
●
Compilador criado em 1985 para linguagem xBase;
●
Ideia surgiu no restaurante (Nantucket), quadro (Clipper);
●
Dados armazenados em arquivos .DBF;
●
Linguagem de execução procedural (v5.2 = 1,6Mb);
●
Durou até a versão 5.3b (1997). Não há mais suporte;
●
Existem iniciativas da comunidade (Flagship);
●
Comandos (USE, SKIP, GOTOP, GO BOTTOM, e GO #);
●
PC: 486 50 Mhz. Memória: 4Mb de RAM, HD: 512 Mb;
●
Outras tecnologias da época:Turbo Pascal, C, Basic, DataFlex.
7. Adianti Solutions Ltda © Pablo Dall'Oglio #7
Procedural
CAD_CLI.PRG
@ 2,5,19,70 window "Cadastro de Clientes"
cCOD_CLI := cad_cli->COD_CLI
cNOME := cad_cli->NOME
cENDERECO := cad_cli->ENDERECO
@ 0,1 say "Codigo_____________ " + cad_cli->COD_CLI
@ 1,1 say "Nome________________" get cNOME pict "@!"
@ 2,1 say "Endereço____________" get cENDERECO
if CONFIRMA("Confirma Alteração ?",20,44)
if cad_cli->(RECLOCK())
cad_cli->COD_CLI := cCOD_CLI
cad_cli->NOME := cNOME
cad_cli->ENDERECO := cENDERECO
cad_cli->(dbunlockall())
endif
endif
Exibe e coleta
Registro trabalhado
como um objeto
Sem SQL
Persistência e concorrência
8. Adianti Solutions Ltda © Pablo Dall'Oglio #8
Procedural
NOTA_FISCAL.PRG
function PROCESSA_NF()
ABRE("RES_NF")
if CONFIRMA("Confirma Nota Fiscal")
res_nf->(dbappend())
if CONFIRMA("Imprimir Nota Fiscal")
PRINT_NF( cSERIE_NF, nNUM_NF, cFILE )
endif
if CONFIRMA("Imprimir Duplicata")
IMPR_DUPLICATA(nNUM_NF, cCOD_CLI)
endif
endif Funções do
User Space
9. Adianti Solutions Ltda © Pablo Dall'Oglio #9
Procedural
CUPOM_FISCAL.PRG
function PROCESSA_CF()
function REGISTRA_CF( nVLR_TOT_CF,... )
function SHOW_TOTAIS()
function CANCELA_ITEM( nITEM, cDESCR )
function BAIXA_ESTOQUE()
function ALTA_ESTOQUE()
function ABRE_CUPOM()
function FECHA_CUPOM( nVLR_TOT_CF, nVLR_PAGO, ... )
function CANCELA_CUPOM( lFICOUABERTO )
function VENDE_ITEM( cCODIGO, cDESCR, nQUANT, nPR_VENDA, cITEM )
function LEITURA_X()
function REDUCAO_Z()
Cadeia de dependências
não muito clara
10. Adianti Solutions Ltda © Pablo Dall'Oglio #10
CA-Clipper
Considerações:
●
Muito rápido e enxuto (Ex: Controle de vendas 841 Kb);
●
Não leva a organização modular, somente separação por funções;
●
Não leva a organização de nomes: Fica a cargo de cada um;
●
Programas geralmente organizados em torno de telas;
●
Não facilita o reuso: Dificuldade identificar partes para reaproveitar;
●
Suscetível à mudanças: Dificuldade em localizar dependências;
●
Diferentes aspectos no mesmo programa:
– Apresentação: @ 0,1 say "Codigo_____________ ";
– Controle: if CONFIRMA("Confirma Nota Fiscal");
– Persistência: cad_cli->(dbunlockall()).
13. Adianti Solutions Ltda © Pablo Dall'Oglio #13
Delphi
Sobre o Delphi
●
Lançado pela Borland em 1995, como substituto doTurbo Pascal;
●
Assim como oTurbo Pascal, foi idealizado por Anders Hejlsberg (DN);
●
Anders Hejlsberg em 1996 move para MS, onde idealizou o C#;
●
Em 2001, foi lançado o Kylix, versão para Linux;
●
Posteriormente, a comunidade criou o Lazarus;
●
Características fortes:
– Programação visual (drag and drop);
– Programação orientada a eventos (OnClick, OnChange);
– Utilização de componentes (TButton, TEdit, TSpinButton);
●
Outras tecnologias da época:Visual Basic, Power Builder.
14. Adianti Solutions Ltda © Pablo Dall'Oglio #14
Delphi
Data Sources, Tabelas
usadas pelo
formulário
Mapeamento entre
objeto visual e BD
15. Adianti Solutions Ltda © Pablo Dall'Oglio #15
Delphi
unit untCadastro;
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, ...
type
TfrmCadastro = class(TForm)
dtbEndereco: TDatabase;
tabEndereco: TTable;
dtsEndereco: TDataSource;
tabEnderecoNome: TStringField;
dgrEndereco: TDBGrid;
Label1: TLabel;
dedCodigo: TDBEdit;
var
frmCadastro: TfrmCadastro;
implementation
Formulário:
Arquivo separado
Data Sources, Tabelas
usadas pelo
formulário
16. Adianti Solutions Ltda © Pablo Dall'Oglio #16
Delphi
procedure TfrmCadastro.FormCreate(Sender: TObject);
begin
dtbEndereco.Open;
tabEndereco.Open;
end;
procedure TfrmCadastro.sbnEditarClick(Sender: TObject);
begin
tabEndereco.Edit;
end;
procedure TfrmCadastro.sbnGravarClick(Sender: TObject);
begin
tabEndereco.Post;
end;
Entra em edição
Envia dados
17. Adianti Solutions Ltda © Pablo Dall'Oglio #17
Delphi
Considerações:
●
Fortaleceu o uso da Orientação a Objetos;
●
Consolidou o conceito de componente de interface (cápsulas);
●
Levou a uma separação entre Interface (.dfm) e Lógica (.pas);
●
Formou uma geração de programadores, acostumada à:
– Arrastar e soltar objetos na tela (drag and drop);
– Programar a lógica orientada à eventos;
– Vincular fortemente o modelo de dados à interface.
●
Não promoveu a tempo uma separação da lógica e do modelo;
●
Essa geração tem dificuldades naWeb, que é orientada à requests.
21. Adianti Solutions Ltda © Pablo Dall'Oglio #21
Início foi dureza...
<?php
// configuração
$conn = pg_connect("...");
// query
$query = 'SELECT id, nome, endereco FROM cliente WHERE id not in (...)';
// resultados
$result = pg_query($conn, $query);
if ($result)
{
// 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);
Business rules
Apresentação
Configuração
22. Adianti Solutions Ltda © Pablo Dall'Oglio #22
Design Patterns
Padrões de Projeto
“Um Pattern descreve um problema que ocorre com frequência em
nosso ambiente, e então explica a essência da solução para este
problema, de forma que tal solução possa ser utilizada milhões de
outras vezes...”
Christopher Alexander (1936 arquiteto)
25. Adianti Solutions Ltda © Pablo Dall'Oglio #25
Frameworks
Frameworks
●
Implementam vários Design Patterns;
●
Fornecem uma arquitetura (arcabouço) para novas aplicações;
●
Conjunto de classes que formam um design abstrato;
●
Genéricos para um domínio de problema;
●
Estendidos para criar APPs específicas;
●
Frozenspots: Partes fixas.
– Serviços já implementados.
●
Hotspots: Partes flexíveis;
– São invocados pelo framework.
26. Adianti Solutions Ltda © Pablo Dall'Oglio #26
ROR
Ruby on Rails (2004)
●
Baseado em MVC (Model-View-Controller);
●
Fornece estruturas pré-definidas para:
– Persistência (Active Record);
– Montagem de tela (ActionView);
– Controle de ação (Action Controller).
●
DRY (Don't RepeatYourself):
– Coluna = propriedade;
– Sem setters e getters.
●
Convention over configuration
– Class User = table Users
27. Adianti Solutions Ltda © Pablo Dall'Oglio #27
TCC
O início do interesse:
●
Em 2004:
– Havia estudado Fowler (2002);
●
Em 2005:
– Precisava de uma arquitetura para oTCC;
– Criei um framework MVC para sistemas;
– Foi batizado de Core Framework;
●
Em 2006:
– Em conversas preliminares, a Univates mostra interesse;
– Adota-o como plataforma para desenvolvimento.
29. Adianti Solutions Ltda © Pablo Dall'Oglio #29
Boom
O boom dos Frameworks:
●
PHP: Zend, CodeIgniter, Cake,
Synfony, Laravel,Yii, Prado;
●
Java: Spring, Hibernate, Castor,
Swing, SWT, Struts, JSF,Vraptor;
●
Pyton: Django,TurboGears;
●
Ruby: ROR, Rack, Cuba, Padrino;
●
Javascript: Angular, Backbone,
Ember, React, GWT, Knockout;
●
C#: .NET, Nhibernate, Castel.
30. Adianti Solutions Ltda © Pablo Dall'Oglio #30
Adianti
Quando surgiu o Adianti Framework:
●
Versão atual iniciou ~2008;
●
Lançado oficialmente em 2012;
●
Focado em Business apps.
33. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #33
Active Record (AF)
Armazenar um novo objeto (INSERT).
class Pessoa extends TRecord
{
const TABLENAME = 'tab_pessoas';
const PRIMARYKEY= 'id';
const IDPOLICY = 'max'; // {max, serial}
}
TTransaction::open('samples');
$object = new Pessoa;
$object->name = 'Maria da Silva';
$object->address = 'Rua da Conceicao';
$object->phone = '(51) 8111-2222';
$object->status = 'S';
$object->email = 'maria@email.com';
$object->store(); // armazena o objeto
TTransaction::close(); // fecha a transação.
Business Rules
34. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #34
Active Record (AF)
Alterar um objeto já existente (UPDATE).
TTransaction::open('samples'); // abre uma transação
$customer = Customer::find(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.
INSERT OR UPDATE
35. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #35
Atalhos (AF)
Manipular um conjunto de objetos conforme um filtro.
$product = Product::find(2);
$products = Product::all();
$products = Product::where('name', 'like', '%Computer%')->load();
$count = User::where('age', '>', 18)->count();
$products = Product::where('name', 'like', '%tablet%')->orderBy('price');
User::where('age', '>', 100)->delete();
Product::where('name', 'LIKE', '%computer%')->take(3)->skip(3);
$contacts = Customer::find(123)->hasMany('Contact');
SQL gerado
com segurança
36. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #36
Active Record (ROR)
Armazenar um novo objeto (INSERT).
class User < ActiveRecord::Base
self.primary_key = "id_user"
end
user = User.new
user.name = "David"
user.occupation = "Code Artist"
user.save
// ou
user = User.create(name: "David", occupation: "Code Artist")
NOT NECESSARY
37. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #37
Atalhos (ROR)
Manipulando Objetos
client = Client.find(10)
users = User.all
david = User.find_by(name: 'David')
users = User.where(name: 'David', occupation: 'Code Artist')
.order(created_at: :desc)
clients = Client.where("orders_count = ?", params[:orders])
clients = Client.limit(5).offset(30)
Articles = Article.where('id > 10').limit(20).order('id asc')
39. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #39
Callbacks (ROR)
Injetando comportamento no ciclo do objeto:
class Account < ActiveRecord::Base
before_save :setupdate, :setloggedin
private
def setupdate
self.Account_Update = Time.now
end
def setloggedin
self.Account_LoggedIn = Time.now
end
end
Callbacks:
before_save
after_save
before_update
after_update
before_destroy
after_destroy
Callbacks:
before_save
after_save
before_update
after_update
before_destroy
after_destroy
Agrega no ciclo de vida
Evita sobrescrita
40. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #40
Hook Methods (AF)
Injetando comportamento no ciclo do objeto:
app/model/SystemProgram.php
class SystemProgram extends TRecord
{
const TABLENAME = 'system_program';
const PRIMARYKEY= 'id';
const IDPOLICY = 'max'; // {max, serial}
public function onAfterStore( $object )
{
// ...
}
public function onAfterDelete( $object )
{
// ...
}
}
Hook Methods:
onBeforeLoad()
onAfterLoad()
onBeforeStore()
onAfterStore()
onBeforeDelete()
onAfterDelete()
Hook Methods:
onBeforeLoad()
onAfterLoad()
onBeforeStore()
onAfterStore()
onBeforeDelete()
onAfterDelete()
Agrega no ciclo de vida
Evita sobrescrita
42. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #42
Controller (ROR)
Executando ações:
/clients/new
app/controllers/clientes_controller.rb
class ClientsController < ApplicationController
def new
end
def edit
end
def delete
end
end
43. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #43
Controller (AF)
Executando ações:
index.php?class=ClienteController&method=onEdit
app/control/ClienteController.php
class ClienteController extends TPage
{
function onEdit() {
// ...
}
function onDelete() {
// ...
}
}
45. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #45
Action View (ROR)
Apresentando templates:
app/controllers/restaurantes_controller.rb
class RestaurantesController < ApplicationController
def index
@restaurantes = Restaurante.all
end
def show
@restaurante = Restaurante.find(params[:id])
end
end
Template:
index.html.erb
Como $this->restaurantes,
Torna-a disponível para a view
46. Adianti Solutions Ltda © Pablo Dall'Oglio Programando para Programadores #46
Action View (ROR)
Apresentando templates:
app/views/restaurantes/index.html.erb
<table>
<% @restaurantes.each do |restaurante| %>
<tr>
<td><%= restaurante.nome %></td>
<td><%= restaurante.endereco %></td>
<td><%= restaurante.especialidade %></td>
</tr>
<% end %>
</table>
47. Adianti Solutions Ltda © Pablo Dall'Oglio #47
Html Renderer (AF)
app/control/TemplateController.php
class TemplateController extends TPage
{
public function exibe()
{
$html = new THtmlRenderer('app/resources/customer.html');
TTransaction::open('samples');
$customer = Customer::find(1);
$replace = ['code' => $customer->id,
'name' => $customer->name,
'address' => $customer->address];
$html->enableSection('main', $replace);
$html->show();
TTransaction::close();
}
}
48. Adianti Solutions Ltda © Pablo Dall'Oglio #48
Html Renderer (AF)
<!--[main]-->
<table class="tform" style="border:1px solid #B7B7B7">
<tr> <td colspan="2">Customer data</div></td> </tr>
<tr>
<td width="50%"> ID </td>
<td width="50%"> {$id} </td>
</tr>
<tr>
<td width="50%"> Name </td>
<td width="50%"> {$name} </td>
</tr>
<tr>
<td width="50%"> Address </td>
<td width="50%"> {$address} </td>
</tr>
</table>
<!--[/main]-->
Replaces
51. Adianti Solutions Ltda © Pablo Dall'Oglio #51
Componentes
Representa um elemento visual, como uma cápsula;
Pode ser reaproveitado em diferentes interfaces.
$this->datagrid = new TDataGrid;
$code = new TDataGridColumn('code', ...);
$name = new TDataGridColumn('name', ...);
$this->datagrid->addColumn($code);
$this->datagrid->addColumn($name);
$act1 = new TDataGridAction(...);
$act1->setLabel('View name');
$act1->setImage('bs:search blue');
$act_group = new TDataGridActionGroup('Actions');
$act_group->addHeader('Available Options');
$act_group->addAction($act1);
$this->datagrid->addActionGroup($act_group);
52. Adianti Solutions Ltda © Pablo Dall'Oglio #52
Componentes
Formulário simples
class SimpleFormController extends TPage
{
private $form;
function __construct()
{
parent::__construct();
$this->form = new TQuickForm;
$this->form->setFormTitle('Quick form');
$id = new TEntry('id');
$text = new TText('text');
$this->form->addQuickField('Id', $id, 40);
$this->form->addQuickField('Text', $text, 120);
$this->form->addQuickAction('Save',
new TAction(array($this, 'onSave')), 'ico_save.png');
parent::add($this->form);
}
54. Adianti Solutions Ltda © Pablo Dall'Oglio #54
Comparativo
Componentes e templates:
●
Templates permitem maior liberdade de criação;
●
Templates oferecem maiores dificuldades de manutenção;
●
É fácil criar templates;
●
Use em: telas peculiares;
●
Componentes são mais limitados no aspecto visual;
●
É melhor de manter um sistema baseado em componentes;
●
É mais complexo criar um componente;
●
Use em: telas padronizadas.
56. Adianti Solutions Ltda © Pablo Dall'Oglio #56
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
57. Adianti Solutions Ltda © Pablo Dall'Oglio #57
Orientação a modelos
Aplicação orientada ao domínio (GOOD)
Utilização de
relações
mais complexas.
Modelo relacional
é consequência
XMI → {PHP, SQL}
58. Adianti Solutions Ltda © Pablo Dall'Oglio #58
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)
}
?>
XML
SQL
PHP
Modelo
Astah
StarUML
59. Adianti Solutions Ltda © Pablo Dall'Oglio #59
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;
}
// adiciona o ator
$ator = new Ator(10);
$filme->addAtor( $ator );
$filme->store();
LEGIBILIDADE
MAIORLazy Load
Agregação
60. Adianti Solutions Ltda © Pablo Dall'Oglio #60
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
$turma = new Turma(10);
foreach ($turma->getMatriculas() as $matricula) {
print $matricula->aluno->nome;
}
NAVEGABILIDADE
entre relações
62. Adianti Solutions Ltda © Pablo Dall'Oglio #6212ª Conferencia Latino-americana de Software Livre
Utilizado em:
Carregar objeto, Salvar objeto, Excluir objeto.
class Disciplina extends TRecord
{
const TABLENAME = 'disciplinas';
const PRIMARYKEY = 'id';
const IDPOLICY = 'max';
const CACHECONTROL = 'Cache-Control-Class';
}
$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;
}
Grandes ganhos de
Performance
1/3 tempo na matrícula
Deve indicar
classe específica
Cache de objetos
63. Adianti Solutions Ltda © Pablo Dall'Oglio #6312ª Conferencia Latino-americana de Software Livre
Cache de objetos
Store: Ele é gravado tanto no banco de dados (a), quanto no cache (d).
Load: Tenta ler da RAM (c). Senão, carrega (b), e grava na RAM (d).
67. Adianti Solutions Ltda © Pablo Dall'Oglio #67
Studio Form Designer
class TestView extends TPage
{
private $form;
function __construct()
{
parent::__construct();
$this->form = new TForm;
try {
$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);
Wrapper
69. Adianti Solutions Ltda © Pablo Dall'Oglio #69
Studio PDF Designer
class PDFDesignNFEView extends TPage
{
function onGenerate()
{
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');
}
//...
Wrapper
70. Adianti Solutions Ltda © Pablo Dall'Oglio #70
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!