Acorda pra Web!

Tecnologia que vai mudar nossas vidas, depois do café.

Um projeto bacana sobre Web Semântica

Monday, December 3rd, 2007

Recentemente foi lançado o novo site do ARC, um projeto do Benjamin Nowack que tem como objetivo criar um sistema que interpreta, cria e trabalha com RDF e SPARQL em geral.

Os planos da sua pequena startup, a SemSol, são de criar um pequeno CMS, o Trice, tendo como base o ARC e com banco de dados todinho em RDF, com consultas todinhas em SPARQL.

O SPARQL (ainda estou devendo um post sobre isso) é a linguagem similar ao SQL desenvolvida pelo W3C especificamente para fazer consultas em fontes de dados RDF, ou seja, para “consultar” nós de Web Semântica.

A idéia é bacana e a plataforma excelente. PHP e MySQL é tão comum que até minha calculadora deve suportá-los. Já tive oportunidade de conversar com o Benjamin sobre o sistema enquanto eu desenvolvia algo similar à primeira versão do ARC Store e suas idéias são realmente legais.

Pode parecer papo de geek, mas o grande objetivo do Trice é mostrar que a Web Semântica pode ser indolor! O aplicativo será aos moldes do WordPress, fácil de usar e instalar. A diferença é o conteúdo, totalmente focado pra essa nova tecnologia.

Provavelmente em alguma versão futura do Base Cube, meu próprio framework, haverá um sistema similar ao ARC desenvolvido totalmente em PHP5 e SQLite, um banco de dados que é um chuchu

Base Cube no Google Code

Thursday, November 29th, 2007

Está no ar a página do meu projeto de framework em PHP5 no Google Code. No post anterior eu já havia mudado temporariamente o nome dele de openIdeo para Base Cube, agora é definitivo.

O nome “openIdeo” eu provavelmente usarei para outro projeto, baseado no framework porém mais próximo de um CMS e não de uma biblioteca.

Para quem não acompanhou, Base Cube é um framework que estou desenvolvendo para PHP5 com características únicas:

  • Não copiar frameworks de outras linguagens.
  • Usar as vantagens exclusivas do PHP5.
  • Não repetir bibliotecas e frameworks já existentes, integrá-los.

Não há por exemplo, uma classe de conexão com bancos de dados nativa. O Base Cube usa as bibliotecas do Zend Framework (única integração disponível no momento) para tal.
Na página principal do projeto há links para uma pequena introdução em português e também a versão em inglês. Há alguns exemplos por lá que podem ajudar!

Ah! E já tem link pra download ;)

O Núcleo do Open Ideo Framework

Monday, August 6th, 2007

O nome do meu framework é Open Ideo. Depois, com mais tempo, eu explico a origem do nome, o propósito e todo o conceito por trás do desenvolvimento.

Nesse release, está presente apenas o núcleo controlador de toda aplicação, que pode servir de base pra trabalhar com qualquer classe em PHP. Baixe aqui o framework com os exemplos do post (execute os arquivos index.php 1, 2 e 3).

O Básico

Atualmente o framework possui um único arquivo, openIdeo.php. Basta colocá-lo no seu diretório web e incluir onde deseja utilizar, assim:

PHP
<?php
require 'openIdeo.php';
?>

Para criar uma classe controladora, declare-a como extendendo oiApp, com o sulfixo App sempre assim:

PHP
<?php
require 'openIdeo.php';
class blogApp extends oiApp
{
function index()
{
echo 'Hello World';
}
}
new blogApp;
?>

Note que no final eu adicionei um new blogApp, é ele que inicia o objeto.

Se você salvar isso como index.php e abrir no navegador, verá a mensagem Hello World, simples e prático. Adicionar uma nova ação é simpes:

PHP
<?php
require 'openIdeo.php';
class blogApp extends oiApp
{
function index()
{
echo 'Hello World';
}
function post($id)
{
echo 'Esse é o post '.$id;
}

}
new blogApp;
?>

Agora, chamando www.exemplo.com/index.php/post/alguma-coisa ele exibirá na tela Esse é o post alguma-coisa. Bastante prático não? Você pode adicionar quantos parâmetros você quiser no método, eles serão passados todos via URL:

PHP
<?php
require 'openIdeo.php';
class blogApp extends oiApp
{
function index()
{
echo 'Hello World';
}
function post($id)
{
echo 'Esse é o post '.$id;
}
function arquivo($ano=NULL,$mes=NULL,$dia=NULL)
{
echo "Arquivos do ano $ano, mês $mes e dia $dia";
}

}
new blogApp;
?>

Se você chamar www.exemplo.com/index.php/2007/07/01 ele mostrará a frase Arquivos do ano 2007, mês 07 e dia 01.

Métodos-Índice (AKA redirecionamento de métodos)

Uma das coisas mais legais do framework, é a possibilidade de criar métodos-índice:

PHP
<?php
require 'openIdeo.php';
class blogApp extends oiApp
{
function index()
{
echo 'Hello World';
}
function post($id)
{
static $index;
echo 'Esse é o post '.$id;
}
function postAdicionar()
{
echo 'Que tal adicionar um post?';
}

function arquivo($ano=NULL,$mes=NULL,$dia=NULL)
{
echo "Arquivos do ano $ano, mês $mes e dia $dia";
}

}
new blogApp;
?>

Agora se você chamar www.exemplo.com/index.php/postAdicionar ele exibirá Que tal adicionar um post?, mas o mais legal é que como declaramos static $index no método post, podemos chamar assim: www.exemplo.com/index.php/post/adicionar, bem mais humano.

Você pode optar por deixar a classe blogApp no arquivo index.php mesmo, ou pode salvá-la no arquivo blogApp.php, ela será carregada automaticamente quando você chamar o novo objeto através do new blogApp; no index.

O Morfador

Adicionalmente, você pode criar várias classes (por exemplo blogApp, enqueteApp e quizApp), e ao invés de chamar por cada uma delas com new, você faz um morfador, assim: oiApp::morph(). O morfador escolhe a classe que será carregada com base na URL, portanto www.exemplo.com/index.php/blog chama blogApp, www.exemplo.com/index.php/enquete chama enqueteApp e assim por diante.

Você pode inclusive limitar seu morfador, chamando oiApp::morph(‘blog|enquete’) ele apenas morfa entre as classes blogApp e enqueteApp, quizApp nunca será carregada por esse morfador. Caso você limite o morfador e ele não encontre o fragmento de inicialização na URL, ele pegará o primeiro da lista de limitações, nesse caso o blog.

Podem ser chamadas quantas classes ou quantos morfadores você quiser. Você pode chamar classes ou morfadores que retornam valores, que exibem coisas, que incluem arquivos. Adicionalmente, escrever módulos para o Open Ideo permite que você controle como eles serão auto-carregados e executados. Essas demais funções do núcleo eu explicarei assim que lançar os próximos componentes do sistema.

Sei que é simples, é apenas um controlador afinal, mas o controlador mais versátil e leve (menos de 4kb) que já vi :) Estou ansioso pra ouvir opiniões e bugs (infelizmente eles existem sempre)!

Meu framework não será MVC

Tuesday, July 31st, 2007

Não totalmente, não esse falso MVC por aí. Em todos os frameworks pra web há um engano conceitual profundo: O View é o HTML.

Por definição, View é a parte da apresentação da aplicação, é a renderização para o usuário do Model. Trocando em miúdos, é aquela coisa que mostramos pro usuário.

Há 10 anos atrás, talvez colocar o HTML como View talvez fosse a melhor saída, mas hoje o HTML é definido como uma camada de informação, não de apresentação.  O HTML tem conteúdo, tem significado, é semântico.

Pensando por esse lado, o HTML está mais próximo do Model do que do View. Um site estático cheio de páginas HTML e um arquivo CSS pra todas também é um framework MVC, o Model é o HTML, o View é o CSS e o Controller é o sistema de arquivos do servidor.

Pode parecer extremamente sujo misturar bancos de dados com HTML, mas não é disso que estamos falando. É possível manter o HTML separado do banco de dados, como uma camada intermediária entre o Model e o View. É um pre-view post-model. Como se não bastasse, o HTML também é Controller, com formulários e links.

Ainda não descobri como resolver o problema do HTML, não posso simplesmente jogar a resposta do banco de dados na página e usar CSS nela. A solução ideal seria usar XSLT como camada intermediária entre o banco de dados e o HTML, mas ele é complicado demais para tornar o framework um facilitador. Imagino que no final, o HTML ficará como uma camada de Model-template.

A maior linha de código

Saturday, July 14th, 2007

Será que no livro dos recordes existe a maior linha de código já escrita? Eu costumo escrever linhas grandes, sou fã de expressões e inevitavelmente elas levam a isso.

No PHP, expressões ajudam bastante a economizar código. Por exemplo, os três trechos abaixo verificam se a variável “var” é numérica, se não for abortam o script:

PHP
if (!is_numeric($var)) {
die;
}

PHP
if (!is_numeric($var)) die;

PHP
is_numeric($var) or die;

O terceiro trecho é simples, é uma expressão binária or. Se a primeira expressão for válida, ele não verifica a segunda. Se a primeira for inválida, ele verifica a validade da segunda. Você só pode fazer esse tipo de expressão com funções que retornam valores, como a die que eu utilizei. Você não pode por exemplo fazer isso:

PHP
is_numeric($var) or return(FALSE);

Return é uma estrutura de linguagem que não retorna valores dentro de uma expressão (retorna eles externamente), portanto não pode ser uma expressão válida e gera um erro.

Outro recurso interessante são as expressões ternárias:

PHP
is_numeric($var) ? print('Ok! Numérico') : die; 

Esse trecho acima equivale ao seguinte:

PHP
if (is_numeric($var)) {
print('Ok! Numérico');
} else {
die;
}

A síntaxe básica é condição ? verdadeiro : falso. Simples e prático, né?

Ah, a maior linha que eu escrevi até hoje foi essa:

PHP
if ($mirror = new ReflectionMethod($obj[0], $obj[1])) $mirror->getStartLine() == $mirror->getEndLine() ? $this->_call(array($obj[0], $obj[1].ucfirst(empty($args[0]) || ($met = !method_exists($this, $obj[1].ucfirst($args[0]))) ? 'index' : $args[0])), $met ? $args : array_slice($args, 1)) : call_user_func_array($obj, $args);

Essa única linha ilegível e complexa (acredite, gosto disso) cria um objeto refletor, verifica se o método chamado é vazio em uma classe e chama um outro método com nome variável com base nos argumentos passados para o método vazio. Caso o método vazio seja passado sem argumentos ele chama um método-índice.

Em outras palavras, ela transforma uma chamada de cliente(‘incluir’,'Alexandre) em clienteIncluir(‘Alexandre’) automaticamente, caso a chamada seja cliente() ele transforma em clienteIndex().

Essa linha faz parte do controlador do meu novo framework, se quiserem usar podem, com algumas condições.

Persistência de objetos

Wednesday, July 11th, 2007

Desde que comecei a escrever meu próprio framework venho buscando maneiras mais eficientes de programar. Obviamente, além das minhas próprias idéias, grande parte das minhas inspirações vêm de sistemas já existentes, frameworks que já funcionam muito bem.

Uma coisa que venho notado, é que algumas funcionalidades viraram moda em determinados frameworks, e ninguém tenta criar algo ainda mais eficiente.

O ActiveRecord por exemplo é um padrão de desenvolvimento que ainda é completamente confuso pra mim. Entendo bem de SQL e de programação em PHP, mas o ActiveRecord não é exatamente nem um nem outro, é uma terceira camada de lógica completamente diferente.

Um dos grandes problemas dele é que não funciona bem com bancos que não sigam o padrão determinado pelo padrão. Uma das coisas que boa parte das implementações do ActiveRecord exige é que toda tabela tenha um campo id numérico como chave primária, o que não acontece em 100% dos casos da vida rea.

Em muitos métodos dos objetos do padrão há mistura de coisas da lógica da linguagem com a lógica do banco, uma péssima prática.

De qualquer maneira, minha proposta não é exclusivamente criticar outros padrões, estou tentando criar algo prático. Não sei se existe algo parecido por aí, mas tive essa idéia durante as últimas noites: Acesso ao banco por um objeto único, com índices de array e métodos embutidos. O melhor jeito de explicar é mostrando exemplos:

PHP
$db->foo[0]; //Primeiro resultado da tabela "foo"
$db->cliente[2]->nome; //Campo "nome" do segundo resultado da tabela "cliente"
$db->foo[0]->nome = "Alexandre"; //Define o campo "nome" do primeiro resultado da tabela "foo"
unset($db->foo[0]); //Exclui primeiro resultado da tabela "foo"
$db->cliente = new clienteRecord; //Cria um novo registro na tabela cliente
$db->cliente->nome = 'Alexandre'; //Define o campo nome do novo registro

Como você pode notar, o acesso ao banco é feito como se todas as tabelas estivessem carregadas dentro de arrays. O maior desafio com certeza é fazer com que o sistema efetue as consultas e alterações sem carregar as tabelas inteiras, para não prejudicar a performance. Usarei sobrecarregamento de arrays e sobrecarregamento em objetos pra isso.

Uma das desvantagens óbvias desse sistema é na hora de buscar por algum resultado. Imagine que tenhamos que buscar todos os resultados com nome igual a “Alexandre”, seria algo assim:

PHP
$busca = array();
foreach ($db->foo as $k => $v) {
if ($v['nome'] == 'Alexandre') $busca[] = $db->foo[$k];
}

É por esse motivo que existem frameworks que implementam métodos de busca aos objetos, alguns similares a esses:

PHP
$db->foo->findByNome('Alexandre'); //Retorna array com os resultados

Se eu quiser por exemplo aumentar o salário de todos os funcionários da limpeza em 20%, faria algo assim:

PHP
$db->funcionarios->findBySetor('limpeza')->salario *= 1.2;

Essa parte dos métodos de busca e demais funcionalidades eu provavelmente não implementarei. O programador terá que fazer algo assim:

PHP
$db->funcionarios('setor = limpeza')->salario *= 1.2;

E obviamente, pode ser que eu não consiga implementar isso de maneira alguma :) Estou encontrando sérios problemas com os métodos de sobrecarga __set no PHP.

Qualquer dica que puderem me dar quanto ao formato e/ou implementação é valiosa.

Meu microframework

Wednesday, July 4th, 2007

Eu tenho mesmo uma implicância com frameworks, os artigos linkados já explicam isso bem. Finalmente coloquei a mão na massa e comecei a desenvolver meu próprio framework, até o momento chamado to95lite. Algumas características do sisteminha:

  • Desenvolvido em PHP5
  • Permite usar SQLite ou MySQL (Talvez funcione com demais bancos do PDO)
  • Não usa XHTML, trabalha somente com HTML 4.01 válido e semântico
  • Contém apenas um arquivo, com no momento 18kb. Pretendo ficar abaixo dos 32kb
  • Gera arquivos de template HTML/PHP válidos, semânticos e simples de modificar
  • Cria micronavegação e formulários automaticamente para as ações: Incluir, Alterar, Visualizar, Buscar e Listar
  • Cria um arquivo CSS sem propriedade alguma, mas com as classes já declaradas para ajudar no desenvolvimento
  • Otimiza as consultas, cria índices e protege contra SQL Injection automaticamente com base nos templates modificados
  • Trabalha com URIs amigáveis, mesmo sem url rewriting por htaccess
  • Permite total tradução do sistema. Por exemplo, eu uso “incluir”, mas você pode usar “criar” ou “adicionar” para as ações se preferir, mudando apenas uma linha do sistema
  • Até o momento não possui sistema de permissões, você tem que se virar com isso
  • Ainda não tem sistema de paginação de resultados (Isso é crítico, no momento ele só retorna 10 resultados de qualquer consulta)

Fiz o teste com o framework essa semana, e com alguns poréns posso dizer que agilizou muito o desenvolvimento, basicamente, o que tive que fazer pra colocar no ar um gerenciador de processos judiciais e andamentos foi:

  • Criar as tabelas e alguns views (pra trabalhar com consultas a múltiplas tabelas) no banco de dados
  • Editar alguns templates, como eu já esperava
  • Usar redirecionamento por HTTP header para tornar alguns dos formulários enviados mais amigáveis
  • Criar um simples sistema de autenticação (15 linhas)
  • Criar o CSS inteiro, já que essa parte do sistema ainda não está pronta

Como já citei, fui forçado a usar bastante as funcionalidades do banco de dados para contornar limitações óbvias do sistema. Com um pouco de criatividade foi simples fazer buscas em várias tabelas e retornar resultados específicos com links pra cada resultado separadamente.

Em breve, coloco por aqui um tutorial e o framwork para download. Provavelmente será de como construir um blog com RSS, comentários e painel de controle autenticado, em 15 minutos (pra superar o Rails, haha).

O Framework do Futuro – Parte 2

Wednesday, May 30th, 2007

Há um tempo atrás escrevi sobre minha insatisfação com os frameworks atuais de desenvolvimento web. Ando polindo a idéia, e cada dia me vejo infelizmente mais longe de um ambiente em que eu possa programar de maneira eficiente.

Testei recentemente o POG, um gerador de objetos para o PHP. Ele é próximo do que eu imaginava, mas só cria a parte realmente básica da programação. Os próprios criadores afirmam que é uma ferramenta e não um framework completo.

Estou lentamente construindo um sistema que use as propostas que apresentei no primeiro post:

  • Criar formulários para relações entre tabelas automaticamente (Adicionar produto ao carrinho, adicionar amigo na lista, adicionar contato, adicionar comentário ao post) baseado em Chaves Estrangeiras, sem nenhuma linha de código.
  • Definir foco da página atual automaticamente. (Essa página é sobre produtos? Sobre contato?)
  • Saber como formatar dados, AKA morte da escrita do HTML. (Como exibir um produto? Como exibir informações sobre uma pessoa? Como exibir informações sobre um mapa?)

O sistema será orientado à objetos, como o POG, mas será centralizado em propriedades. O que isso significa?

Um sistema orientado à objetos e centralizado em objetos possui objetos (meio óbvio não?) e cada objeto tem propriedades internas exclusivas do objeto.

No meu sistema as propriedades serão livres. Ao invés de ter um objeto produto com a propriedade preço e um outro objeto serviço com outra propriedade exclusiva preço, terei os objetos produto e serviço e a propriedade preço configurada para adequar-se a ambos. Na verdade, as propriedades no meu sistema também são objetos, os mais importantes.

Essa centralização em propriedades é baseada no esquema de vocabulários da Web Semântica, e todo o sistema utilizará esquemas de vocabulários ao invés de esquemas de bancos de dados.