segunda-feira, 14 de dezembro de 2009

PHP Symfony, vale a pena!

Nesse último sabado tive a oportunidade de palestrar no GOPHP Conference, falei um pouco sobre symfony, assisti palestras legais e interagi com os colegas ali presentes. Foi muito legal, parabéns mais uma vez ao grupo.

Segue o link para a palestra:
http://www.slideshare.net/marcelomf/php-symfony-vale-a-pena

[]s

quinta-feira, 22 de outubro de 2009

MVC interoperando

Tivemos uma thread esse mês sobre MVC sem SGBD's no DFJUG, como não tenho um link público, irei colar a minha opinião exposta lá:

“Não tenho um SGBD, preciso de model ?”

...

Os arquivos são os seus dados....ou seja, seu banco de dados. Ai você pode ter os dto's que são a representação dos seus objetos abstrai-dos dos seus dados(seus arquivos) e o dao para acesso/persistência de dados, ou seja, o trabalho de parsing dos seus dados e talvez manipulação(ler os arquivos e alimentar dto's, talvez realizar uma regra de negocio a salvar no arquivo ou em outro... depende do que você quer). Logo, você tem sim um model... se você quiser né... você é livre para escolher a arquitetura que melhor te atende.

O que vai determinar se sua aplicação é em MVC, é a independência das camadas e o fluxo dos dados... vamos supor que agora os seus arquivos são xml's e não txt... pois bem, você deve alterar somente o seu model e a aplicação deve continuar funcionando normalmente.

Agora você quer um view em jsf ou flex, sendo que antes era jsp... blz, agora você deve alterar somente o seu view e a aplicação deve continuar funcionando normalmente.

E o seu controller ? Deve ser capaz de fazer o que cujo dito acima. Mas vamos supor que agora você quer tirar o sistema da WEB e fazer ele rodar no console ou com swing, então você vai ter que alterar o seu view e o seu controle, mas o model, você pode reutilizar sem drama nenhum...

Com relação a distribuição de pacotes e classes, isso vai depender do tamanho do projeto, do que você quer com ele, particularmente eu não conheço nenhuma regra pra isso envolvendo mvc... acredito que o importante mesmo é o fluxo dos dados ser correto e existir essa certa independência entre camadas, mesmo que o controller esteja "mais preso" ao view...

Para saber mais:
http://java.sun.com/blueprints/patterns/MVC-detailed.html
http://www.moock.org/lectures/mvc/
http://en.wikipedia.org/wiki/Model-view-controller

Grande parte das framework's MVC's pecam por não interoperar entre arquiteturas/linguagens. Acredito que a arquitetura MVC em si seja legal, mas as implementações da mesma deixam a desejar. O controller deve ser reaproveitado para diferentes arquiteturas/linguagens, a renderização do resultado do model, realizada pelo controller, deve ser reaproveitada em diferentes view's. É necessário que o controller seja totalmente desacoplado do VIEW. Para fazer isso de maneira interoperável, penso na seguinte solução:

Model → ORM(EJB3, Doctrine, Propel, etc).
Controller → REST(Assim eu consigo interoperar e estabelecer uma comunicação simples com o VIEW)
VIEW → XHtml, JavaScript, ActionScript(Flex).

Dessa forma, eu consigo inclusive desenvolver webservice's embarcados, com frontend's distintos.  Hoje, se juntarmos pedaços de framework's, conseguimos implementar facilmente uma arquitetura similar a exposta, mas precisamos mais do que isso... precisamos que códigos sejam gerados... trabalho de maquina, deve ser feito por maquina, o designer deve fazer designer e o desenvolvedor deve codificar negócios e ou arquitetura. Particularmente eu desconheço uma framework que gere código em cima dessa arquitetura, grande abraço a todos!

quinta-feira, 8 de outubro de 2009

Interoperabilidade entre linguagens


Pesquisando um pouco sobre computação distribuída, objetos distribuídos, grid computing, cloud computing e etc. Pensando em uma aplicação na qual não interessa a linguagem e sim o serviço, logo vem a minha cabeça os webservice's, soa, etc. Mas hoje, estava procurando por algo mais robusto, sem a necessidade de se ter um httpd por exemplo.

Comecei lendo sobre rmi, corba, jini, jxta, jms e acabei chegando em ICE(Internet Comunications Engine) e consequentemente no projeto zeroC que inclusive tem a participação de alguns artistas responsáveis pelo corba. Baixei o manual e fiquei impressionado com tanta documentação e no poder que a tecnologia pode me fornecer e no quanto a complexidade envolvida parece ser abstraída. Abaixo o site do projeto:
http://www.zeroc.com/

Depois de algumas pesquisas, conheci outros projetos nessa mesma linha, com destaque para o ActiveMQ da apache, outros podem ser encontrados aqui:

Estou desenvolvendo um projeto que envolve computação distribuída e segurança da informação. O mesmo será open source! Estou terminando a parte de firewall para disponibilizar os códigos e quem sabe contar com a colaboração da comunidade.
[]s

terça-feira, 29 de setembro de 2009

Migrando dados entre SGBD heterogêneos

No início do ano foi me dada a tarefa de sincronizar 2 bases de dados(+300 tabelas de alguns gigas) entre SGBD's distintos(db2 -> mysql), estando limitado a um link de 512kb para a transferência dos dados. Pesquisei diversas soluções open source's e proprietárias, as soluções proprietárias para realizar ETL foram descartadas pela empresa devido ao custo. Logo, me sobrou as soluções open source, oba ;).

Como já era de se esperar, eu não encontrei nenhuma solução open source que se encaixasse como um luva para o me problema, mais tudo bem, é nesse momento que entra a diversão xD. Dividindo a esquemática em 2 etapas, temos:

   1.Migrar o DDL, deixando que o novo banco de dados(slave/destino dos dados/mysql) tenha a estrutura semelhante ou igual ao do banco já existente(master/origem dos dados/db2).
   2.Migrar e sincronizar os dados todas as noites, pois não fazia parte dos requisitos da solução uma sincronização “on the fly”.

No início eu estava procurando por features do próprio banco de dados para tentar trabalhar com task's e procedure's, li algumas coisas sobre dblink(postgresql/mysql)/data federation(db2), mas como o meu acesso ao ambiente de origem era restrito(ddl dos schema's e view's para acessar os dados) eu tive que ir para outro rumo. Antes de começar a falar sobre o dbmt(http://sourceforge.net/projects/dbmt/) software que me ajudou a resolver o problema, quero citar outros 2 projetos que me chamaram a atenção, mas que infelizmente não deu para serem aplicados na minha realidade(restrições de acesso no ambiente de origem), são eles:
http://symmetricds.codehaus.org/
http://www.drbd.org/

Para migrar o DDL foi utilizado o mysql migration tools, existe diversas ferramentas que fazem isso, o melhor é pegar uma especifica do seu banco destino(no meu caso mysql)... testei varias e mesmo o mysql migration tools não funcionou 100%, pois tive que migrar schema por schema e consertar algumas foreign key na mão(isso porque o mysql não suporta foreign key entre schemas, já o DB2 sim). Depois de estar com o DDL 100%, realizei algumas alterações na nomeclatura das tabelas para atender melhor ao padrão de modelagem de dados da empresa onde trabalho. Feito isso, fui para a segunda etapa, customizar o DBMT para migrar e sincronizar os dados todas as noites.

O dbmt é software open source escrito em java que realiza a engenharia reversa em uma fonte de dados(jdbc/xml/csv/dbf) e gera um xml relacionado a fonte de origem e de destino, bem como suas tabelas e colunas. É exatamente o que eu pensei em fazer na época, mas graças ao open source consegui pronto ;), mas como eu tinha dito antes, não foi lá as mil maravilhas, então vamos aos fatos.

Todas as noites o banco de dados de destino(mysql) tinha as suas tabelas truncadas e os seus dados eram reimportados do banco origem(db2), isso é algo bastante ruim, pois eu não queria perder tempo/banda, trazendo novamente dados que eu já tinha e que não sofreram alterações(a regra de negócio me garantia isso)... para resolver isso, comecei a trabalhar nas tabelas mais criticas em termos de tamanho (tabelas de movimentação financeira/contábil) e passei a trazer os registros a partir do último registro que eu possuía, na realidade alguns registros para traz, utilizando unique's compostas, eu conseguia garantir que jamais teria um dado duplicado. Isso vai depender muito do seu negócio e da sua necessidade.

Para migrar dados com o dbmt, você passa por 2 etapas, são elas:

   1.Criação do xml.
È aqui que altero o xml que será gerado, buscando atender as minhas necessidades e que verifico os últimos registros das tabelas de movimentação no banco destino(mysql) e crio as condições/where's que serão executadas lá no banco de dados origem(db2), isso para ganhar tempo. Para fazer isso, foi necessário alterar a classe:
      1.CreateMigration
         1.Criei também 2 métodos, um para adicionar prioridade para determinadas tabelas e outro para bypassar determinadas tabelas.
         2.Uma classe para conexão jdbc ao meu banco destino(mysql).
         3.Uma classe para geração das condições/where's de cada tabela que é feito de acordo com a “regra de negócio de persistência” das mesmas.
         4.Alterei o método extractTable() para gerar as tabelas e colunas de acordo com a nomeclatura padrão do meu banco destino(mysql).
   2.Importação dos dados.
Uma vez que o xml está gerado, o dbmt utiliza o mesmo para começar a importação. Nessa etapa eu tive 2 problemas:
      1.Precisava desabilitar a checagem de integridade de referencia das foreign keys no mysql, para isso, alterei o método initTarget da classe MigrationJDBC e adicionei as seguintes variáveis de conexão:
?autoReconnect=true&sessionVariables=FOREIGN_KEY_CHECKS=0
      2.Outro problema estava relacionado ao SqlJep que o DBMT utiliza para a aplicação dos where's, o SqlJep busca ser uma linguagem padrão para DML em SGBD's distintos, o problema é que o where erá aplicado em cima do resultset select * from dborigemDB2.nome_tabela, ou seja, o where não erá aplicado diretamente no banco de dados origem(db2) e sim seu resultset(do select * from...), dessa forma, toda a economia de banda que eu teria ganhando criando os where's dinâmicos na etapa 1(criação do xml) seria perdida... para resolver isso, foi necessário alterar o método initSource para não utilizar o sqljep e aplicar o where diretamente no banco de dados origem(db2), o ruim disso é que o DML desse select teve que ser padrão DB2 que por sinal é bem chatinho, mas nada que uma googada não resolva.

Se você achou interessante essa solução, baixe o source do dbmt e estude principalmente as classes: CreateMigration, Migration, MigrationJDBC e Step. Não deixe de criar rotinas que possam validar realmente a integridade dos dados entre origem/destino, é isso! Abraços.

sexta-feira, 11 de setembro de 2009

PHPIDS - IDS incorporado na sua aplicação


Quero compartilhar com vocês um projeto que conheci através do colega Wagner Elias, chama-se PHPIDS, através de assinaturas que utilizam expressões regulares você cria filtros que tem o objetivo de detectar ataques que exploram a falta de tratamento na entrada de dados, como iSQL, XSS(para + veja owasp). O legal é que conseguindo diminuir os falsos positivos, você pode por exemplo integrar o phpids a sua camada de controle e fazer com que o mesmo funcione como um IPS.
Outro fato importante é que você aproxima a segurança da equipe de desenvolvimento e que a segurança fica incorporada a sua aplicação e não ao seu servidor de aplicação e ou protocolo de comunicação(http), como no caso de se usar o mod_security do apache para WAF, mesmo que com proxy reverso você consiga fazer o filtro em um ambiente destinto da aplicação e até mesmo de outros servidores de aplicação que não o apache, mas é importante lembrar que com o mod_security o tratamento se restringe a tráfego http que você acaba criando mais um vetor de ataque(alá falhas do mod_proxy), além de que com mod_security, normalmente a configuração do mesmo fica atrelada a equipe de infra e não a de desenvolvimento.
Gostei muito do projeto, gostaria de saber se existe algum semelhante em java e o mais legal, seria poder compartilhar regras entre os mais diversos IDS's, para evitar retrabalho... desconheço um projeto que se preocupe com a interoperabilidade de regras entre IDS's.
O Wagner Elias vai palestrar sobre o phpids na PHPConference 2009, inclusive, levantando a possibilidade de integrar o mesmo ao memcached, evitando ou minimizando assim o overhead.
Abaixo um filtro do PHPIDS:
<filter>
<id>44</id>
<rule>
(?:\d"\s+"\s+\d)|(?:^admin\s*"|(\/\*)+"+\s?(?:--|#|\/\*|{)?)|(?:"\s*or[\w\s-]+\s*[+<>=(),-]\s*[\d"])|(?:"\s*[^\w\s]?=\s*")|(?:"\W*[+=]+\W*")|(?:"\s*[!=|][\d\s!=+-]+.*["(].*$)|(?:"\s*[!=|][\d\s!=]+.*\d+$)|(?:"\s*like\W+[\w"(])|(?:\sis\s*0\W)|(?:where\s[\s\w\.,-]+\s=)|(?:"[<>~]+")
</rule>
<description>
Detects basic SQL authentication bypass attempts 1/3
</description>
<tags>
<tag>sqli</tag>
<tag>id</tag>
<tag>lfi</tag>
</tags>
<impact>7</impact>
</filter>

Para saber mais:

quinta-feira, 10 de setembro de 2009

Começando com o symfony

Diversos colegas já me pediram ajuda para começar com o symfony, então eu enviava um email para eles explicando o básico sobre o symfony(escrito referenciando a versão 1.0, mas sem grandes dramas para a 1.2), segue abaixo o conteúdo do email.

Ele usa o propel para orm ou o doctrine, a versão 1.3 do propel está usando o pdo para abstração de dados, enquanto que a 1.2 utiliza o creole, o doctrine já nasceu usando o pdo... é mais vantagem utilizar o PDO pois o mesmo tornou-se nativo no php, recomendo então que você utilize o symfony com a versão 1.3 do propel ou com o doctrine...

o symfony funciona em MVC e com as seguintes particularidades:

1 - Preparar o apache para o symfony funcionar... habilitar o mod_rewrite e criar um Alias...(na documentação em anexo ensina isso)

2 - Modela-se(http://sourceforge.net/projects/dbdesigner-fork) o banco de dados seguindo os padrões que o symfony exige, exemplo:
Chave primaria -> id
Chave estrangeiras -> tabela_id
boolean como tinyint...

3 - Cria a pasta do projeto(mkdir projeto) e dentro dela cria-se o projeto com symfony init-project e depois cria-se a aplicação com symfony init-app.

4 - Faz-se a engenharia reversa no banco com o intuito de gerar o schema.xml/schema.yml utilizado pelo propel para criar o modelo, symfony propel-build-schema (antes você tem que configurar config/databases.yml e propel.ini )

5 - Gerar o model com symfony propel-build-model, as classes ficam em lib/model, em lib/model/om ficam as classes que ele realmente gerou... as que ficam no model são as que você ira adicionar código... seja para persistência ou regra de negocio. Lendo a documentação você consegue trabalhar com pacotes! Para criar pacotes com classes que não tem a ver com o banco, procure sobre autoload, além disso você pode trabalhar com mais de um banco de dados, basta configurar o databases.yml corretamente.

6 - Gerar o view e o controle com propel-init-admin, existe o generete-crud e init-crud, de longe eu prefiro o init-admin, pois o código gerado segue os padrões tableless..., uma vez gerado com o
init-admin você precisa aprender a utilizar o generators.yml que é o que "configura" o VIEW... para telas mais trabalhadas eu prefiro criar a pasta templates no modulo da aplicação e copiar do cache o código gerado do view, copio só o que preciso e altero... é bom dar uma lida no código gerado na pasta cache... só assim para entender legal como funciona o controle e o view...

Dos framework's que eu olhei na época(meados de 2007... cakephp, phpinsigner, symfony, zend) o symfony é o que tem uma maior curva de aprendizado... mais de longe era o melhor estruturado e que me fornece total possibilidade de customização... recomendo ele fortemente!

links:
http://www.symfony-project.org/doc/1_0/
http://symfony-brasil.com/
http://trac.symfony-brasil.com/

plugins:
http://trac.symfony-project.com/wiki/SymfonyPlugins

lista:
http://groups.google.com/group/symfony-pt/topics


Framework php ? Symfony!

Utilizar framework's que agilizam e padronizam o desenvolvimento de código é uma ótima idéia! O que não quer dizer que seja fácil. Comecei utilizando o symfony como framework php, acredito ter feito uma ótima escolha, mas hoje enfrento algumas dificuldades que quero compartilhar com vocês:

  1. Um grande problema é querer usar tudo que o framework oferece sem entender a fundo a sua arquitetura, as vezes você chega em uma solução e mais pra frente descobre que o mesmo resultado poderia ser alcançado de maneira mais elegante. Portanto, sempre que você estiver diante de algo novo, além de pesquisar em listas de discussões e dar um googada, reúna todos os diagramas que você tem referente a arquitetura da framework e identifique as classes relacionadas ao seu problema, pegue a documentação da api e leia toda a documentação das classes identificadas.

  2. As vezes a api da framework não irá te atender e será necessário criar um novo método ou até mesmo classe que irá interagir diretamente com a arquitetura, nesses casos, releia a documentação e tenha a certeza de que a framework realmente não te atende :), caso ela realmente não te atenda, procure estender as classes da framework e codificar sua própria classe, documente bem toda a alteração e submeta a mesma ao projeto da sua framework(principalmente se o mesmo for open source). Lembre-se de garantir que em uma próxima versão da framework, as suas alterações irão funcionar perfeitamente.

  3. As vezes, os kras da sua framework decidem fazer alterações significativas na próxima versão da mesma e nesse caso é bom que você tenha um bom plano de ação para integrar as aplicações da versão anterior com a atual, acredite, se você quer utilizar framework's terceiras, é bom que você se preocupe com isso! Técnicas de roteamento e sandbox podem te ajudar bastante.

  4. Jamais utilize features da framework sem antes garantir a eficácia das mesmas, não é porque funcionou hoje que sempre irá funcionar! Sanitize todos os dados de entrada, garanta que sua framework faça isso! Esmiúce ao máximo todo o fluxo referente a controle de acesso, leia os fontes e faça muitos testes!

Agora que eu desabafei com vocês sobre minha experiência com o symfony, destaco que a versão 1.2 está com uma série de melhorias quanto a parte de form's com a utilização de object forms(+widget's, +validators), além da integração com o doctrine(orm que utiliza o PDO para abstração de acesso a dados e utilizando o padrão active records) nativa.