domingo, 4 de maio de 2008

Magma: persistência de dados no Squeak

Squeak Apesar de eu ter gostado bastante do GNU Smalltalk e sua facilidade em executar scripts, o Squeak é fascinante e tremendamente completo.

A Cincom deveria ficar com vergonha de vender o Visual Works, não porque o Visual Works seja ruim – pelo contrário! É uma senhora ferramenta – mas porque o Squeak dá de dez a zero nele. Aliás até o Eclipse ficaria pra trás do Squeak se não suportasse outras linguagens além de Java.

Você pode encontrar um pouco mais sobre Visual Works na Superfície Reflexiva.

Voltando ao Squeak, que é parte do foco deste artigo, vamos falar agora de persistência de dados.

O Squeak oferece algumas bibliotecas de interface com RDBMS's, como MySQL e PostgreSQL. Mas hoje vamos falar de Magma.

Magma é uma biblioteca de banco de dados multiusuário orientado a objetos. Para instalar Magma, abra o SqueakMap Package Loader e instale os pacotes Magma client e Magma server – a versão que estou usando é 1.0r40.

Magma pode ser usado de duas formas: ¹arquitetura cliente-servidor ou ²em modo monousuário (single-user).

Vamos começar com o modo monousuário, pois é mais simples, depois entender a arquitetura cliente-servidor não vai ser nenhum bicho de sete cabeças – principalmente pra quem já trabalha com RDBMS.

A primeira coisa que precisamos fazer é criar o repositório. Para tanto, crie um diretório em algum lugar, vou criar em /tmp/magmaRepository, depois abra um workspace e digite:
" Create repository "
MagmaRepositoryController
create: '/tmp/magmaRepository'
root: Dictionary new.


Se você estiver usando o Windows e quiser criar o repositório em C:\Magma Repository, pode proceder da mesma forma, basta lembrar de sempre substituir /tmp/magmaRepository pelo path do Windows que você escolheu.

Selecione todo o texto, clique com o botão azul (do meio do mouse) e escolha do it. Quando o Magma terminar de criar o repositório, já podemos fechar o workspace e criar a classe que representará nossa tabela.

Para teste, criei uma classe Person:

No System Browser crie um pacote Kodumaro, nele crie a seguinte classe:
Object subclass: #Person
instanceVariableNames: 'firstname lastname birth'
classVariableNames: ''
poolDictionaries: ''
category: 'Kodumaro'


Crie então os seguintes métodos na classe – não vou entrar em detalhes sobre como fazer isso, é fácil e você pode encontrar no Google:
initialize

firstname := ''.
lastname := ''.
birth := null.


Crie também os métodos acessores:
birth
↑ birth


O sinal você consegue com ^.
birth: aDate
birth := aDate.

firstname
↑ firstname.

firstname: aName
firstname := aName.

lastname
↑ lastname.

lastname: aName
lastname := aName.

fullname
↑ firstname, ' ', lastname.

[update 2008-05-07]Uma coisa legal é que você não precisa criar diretamente os métodos acessores – getters e setters para a galera do Java –, como fizemos acima.

Você pode clicar com o botão azul sobre a lista de categorias ou sobre a lista de métodos, ir em refactor instance variableaccessors e escolher o atributo, então o Squeak cria os métodos acessores pra você![/update]


E os métodos de exibição:
printString
↑ self fullname, ': ', birth printString.

printOn: aStream
self printString printOn: aStream.


Clique com o botão azul (do meio) sobre as yet unclassified e em seguida em categorize automatically, em seguida mova fullname para accessing.

Já temos então nossa classe Person, podemos povoar a base.

Abra um workspace e digite nele:
| coll mySession user1 user2 user3 |
user1 := Person new
firstname: 'Rodrigo';
lastname: 'Cacilhas';
birth: (Date newDay: 20 month: 11 year: 1975).

user2 := Person new
firstname: 'Walter Rodrigo';
lastname: 'Cruz';
birth: (Date newDay: 8 month: 12 year: 1981).

user3 := Person new
firstname: 'Claudio';
lastname: 'Torcato';
birth: (Date newDay: 13 month: 5 year: 1977).

coll := MagmaCollection new.
coll
add: user1;
add: user2;
add: user3.

mySession := MagmaSession openLocal: '/tmp/magmaRepository'.
mySession connectAs: 'cacilhas'.
mySession commit: [
mySession root
at: 'kodumaro'
put: coll
].
mySession disconnect; closeRepository.


Selecione todo o código, clique o botão azul (do meio), selecione do it, depois limpe o workpace para que possamos reaproveitá-lo.

Abra um Transcript e edite o workspace par fazermos uma consulta:
| mySession |

mySession := MagmaSession openLocal: '/tmp/magmaRepository'.
mySession connectAs: 'cacilhas'.

(mySession root at: 'kodumaro') do: [ :col |
Transcript show: col printString; cr
].

mySession disconnect; closeRepository.


Os objetos na base de dados devem ser exibidos no Transcript.

Modelo cliente-servidor


O modelo cliente-servidor é trivial: levantar servidor, conectar com o cliente, fazer as consultas, desconectar. Quando não for mais usar, pare o servidor.

Para levantar o servidor, no workspace execute:
" Start server "
MagmaServerConsole new
open: '/tmp/magmaRepository';
processOn: 51001;
inspect.


Selecione o código, botão azul (do meio) e do it. Isso iniciará o servidor ouvindo na porta 51001/tcp e abrirá uma janela de inspect para o console do servidor – que poderemos usar para pará-lo.

Abra um workspace – ou reaproveite o que está aberto – para podermos fazer uma conexão cliente – abra também o Transcript, se já não estiver aberto:
| mySession |

mySession := MagmaSession
hostAddress: #(127 0 0 1) asByteArray
port: 51001.

mySession connectAs: 'cacilhas'.

(mySession root at: 'kodumaro') do: [ :col |
Transcript show: col printString; cr
].

mySession disconnect.


Selecione o código, botão azul (do meio) e do it.

Para parar no servidor, no inspect do console digite:
self shutdown


Botão azul (do meio) e do it.


Não que alguém vá trocar – por enquanto – um RDBMS pelo Magma, mas já é algum conhecimento para quando os SGBD's orientados a objetos estiverem mais maduros.

[]'s
Cacilhas, La Batalema

PS: Por favor nenhum comentário sobre ZODB estar bem maduro, já sabemos disso. O Magma é que ainda não está.
blog comments powered by Disqus