Ventury Networks’ Blog

“If it walks like a duck and quacks like a duck, I would call it a duck.”

Créer un objet à partir d’une chaine de caractère


La syntaxe de Smalltalk définit un bloc de la manière suivante :

bc := [ :a | a traitements. a.].

Ici, le bloc est paramétré. Lors de l’execution du bloc, le message “traitements” est envoyé au paramêtre. Le bloc renvoie la dernière valeur évalué. Ici, il s’agit explicitement de a.

Pour évaluer le bloc, je peux faire :

monObjet := MonObjet new.
bc value: monObjet.

Très bien. Admettons maintenant que je dispose de la chaine de caractère suivante :

' [ :a | a traitements. a.]'

Je souhaite en faire un bloc comme précédemment (en quelque sorte, compiler le code). Et bien, il suffit pour cela d’appeler la méthode readFromString: de Object :

bc := Object readFromString: '[ :a | a traitements. a.]'.
monObjet := MonObjet new.
bc value: monObjet.

Et voilà. Je vous invite à essayer la même chose avec les lignes suivantes (faites un “inspect” dessus pour voir ce que cela donne) :

Object readFromString: '34'.
Object readFromString: 'coucou'.
Object readFromString: '''coucou'''.
Object readFromString: 'a := String new.'.
Object readFromString: 'a := ''coucou''. b:= 5. '.

Note : dans une chaine de caractères, le caractère spécial ‘ (guillemet simple, ou “simple quote”), est échappé par son doublage. Ainsi, au sein d’une chaine de caractères entourées par des guillemets simples, ”  ( ‘ suivi de ‘, et non “) représente un guillemet simple (et non la terminaison de la chaine).

Tags :

Créer un fichier avec VisualWorks Smalltalk


On souhaite créer un fichier, et y écrire du contenu. Le code suivant permet de créer le NOUVEAU fichier “test.txt” et d’y écrire un mot :

| file |
file := 'test.txt' asFilename.
file exists ifFalse:
	[ | ws |
	ws := file writeStream.
	ws nextPutAll: 'coucou'.
	ws close.]

Pour lire le contenu, on peut faire :

| file contenu |
file := 'test.txt' asFilename.
file exists ifTrue: [ | rs |
	rs := file readStream.
	contenu := rs contents.
	rs close.].
^contenu
Tags :

Smalltalk et les blocs multi-paramétrés


La problématique est la suivante : comment passer trois paramètres à un bloc, provenant d’une collection (Array, OrderedCollection, ou tout autre …).

monTab := #(1 2 'add').
monBloc := [:op1 :op2 :op3 | duCode. ^unResultat].

Je veux executer monBloc avec le contenu de monTab comme paramètres. L’utilisation de do: n’est ici pas appropriée : do: est un message compris par une collection, pas par un bloc. Et pourtant, la réponse est dans cette réponse : un bloc est un objet, comme tout en smalltalk. Il existe donc un message permettant de donner un paramètre à un bloc. Ce message est value: :

monBloc := [:op1 :op2 :op3 | duCode. ^unResultat].
monBloc value: 1 value: 2 value: 'add'.

Pour obtenir les éléments de monTab, je propose l’utilisation d’un ReadStream. Cependant, un acces direct aux éléments est aussi possible. Voici les deux solutions :

monTab := #(1 2 'add').
monBloc := [:op1 :op2 :op3 | duCode. ^unResultat].
" Accès direct aux éléments "
monBloc value: (monTab first) value: (monTab at: 2) value: (monTab last).
" Une seconde solution : "
monStream := monTab readStream.
monBloc value: monStream next value: monStream next value: monStream next.

Et voilà !

Tags :

Un serveur express en perl


Il arrive des fois où l’on a besoin de tester une application, et que pour cela un serveur logiciel est necessaire. Le cas s’est présenté récement : j’avais besoin d’un serveur qui écoutait sur un port, et affichait sur la sortie standard les paquets qu’on lui envoyait.

L’application client que je voulais tester était en Java. J’aurrais pu faire un serveur approprié en Java, mais … c’est tellement long. J’ai préféré utiliser un petit serveur bidon écrit en perl, qui réalise pleinement ce que j’attends, dont je vous donne ici le code source :

#!/usr/bin/perl
use strict;use warnings;
use IO::Socket;

my $serveur = IO::Socket::INET->new(LocalPort => 12345,
                                    Type      => SOCK_STREAM,
                                    Reuse     => 1,
                                    Listen    => 10)
or die "Impossible serveur tcp sur le port 12345 : $@\n";

while(my $client = $serveur->accept())
{
	while( my $rep = <$client>) {
	    print $rep;
	}
}

Il s’agit d’une version simplifiée d’un exemple trouvé sur internet il y a de cela quelques temps. Dans la doc Perl probablement ? Quoi qu’il en soit, la modif apporté fait que le serveur ne fork pas lors de l’arrivée d’un nouveau client : il s’agit là d’un serveur monoclient. Mais franchement, c’était largement suffisant !
Je vais sans doute utiliser ce serveur pour tester BOSS sur une connection TCP.

Tags :

Upgrade Fedora 7 -> 8


Upgrade Fedora via YUMNote importante rédigée le 13 mai 2008 : Pour mettre à jour votre Fedora 7 ou 8, vous feriez mieux d’utiliser la méthode, bien plus sure, de PreUpgrade. Un tutoriel en images vous explique comment réaliser cette opération.

Vendredi dernier, quelques jours avant le réveillon, j’ai eut l’occasion de faire une mise à niveau d’une installation Fedora 7 vers la dernière Fedora 8.

Contrairement à ma précédente expérience, qui je l’avoue, était un peu kamikaze, celle-ci c’est parfaitement déroulée.

J’ai pour cela suivit la roadmap simple et traduite en français du wiki francophone de Fedora. Celle ci apparait - et c’est regrétable - assez loin dans une recherche google (à moins de savoir exactement ce que l’on cherche ;-) ). Il suffit pourtant de suivre à la lettre ce qui est écrit.

A l’issue de cette mise à jour via yum (pas si longue que cela, pour une connexion ADSL 1Mega…), une dépendance n’avait pas été ajoutée (je l’ai ajoutée à la main : yum install lepaquet), et un paquet ne s’est pas désinstallé correctement (une vieille version de avahi me semble-t-il… mais, “who cares ?“… ). L’étape 3 du HOWTO permet de détecter ce genre de problèmes. On peut alors en régler certains…

Bref, je suis plutôt satisfait de l’opération, et je me dis que la prochaine fois, l’utilisateur en question pourra se débrouiller sans peines tout seul. Car, même si cela flatte l’égo d’être indispensable, ca n’est pas bon pour les nerfs…

Je vais peut être m’installer une vieille FC5 sur une machine virtuelle, et tenter l’upgrade direct FC5 -> F8, pour rigoler :-)-

Post Scriptum : C’est Fait !

Tags :

Binary Object Stream Service


VisualWorks propose un Parcel nommé BOSS, pour Binary Object Stream Service. Celui ci permet le stockage d’instances sous la forme d’un fichier binaire. Ce parcel est normalement chargé dans l’image de départ de VW 7.5, mais le cas échéant, il peut être chargé via le parcel manager (”System” -> “Parcel Manager”). Il se trouve dans l’onglet suggestion, et le dossier “Application Developpement”.

Le code suivant permet d’utiliser BOSS :

myWriteStream := 'monFichier.dat' asFilename writeStream.
bos := BinaryObjectStorage onNew: myWriteStream.
"on suppose qu'il existe anObject, une instance de classe quelconque..."
[bos nexPut: anObject] ensure: [bos close].

On pourrait tout aussi bien utiliser le message “nextPutAll: aCollection” pour stocker un ensemble d’instances. La construction [aBlockClosure] ensure: [anAction] retourne la valeur retournée par le premier block, mais, avant cela, évalue le second bloc.

Pour récupérer des instances d’objets, le problème n’est pas plus compliqué :

myReadStream := 'monFichier.dat' asFilename readStream.
bos := BinaryObjectStorage onOldNoScan: myReadStream.
[myObjects := bos contents] ensure: [bos close].

Il est également possible de stocker des définitions de classes, avec le message “nextPutClasses: anArray” (anArray doit contenir les classes à enregistrer). Pour les récupérer depuis la sauvegarde, le message nextClasses fera l’affaire ;-)

BOSS est capable de détecter les changements dans la définition des classes lors du chargement d’instances depuis un fichier BOSS. Ainsi, vous pouvez diffuser un patch contenant les nouvelles classes oou les modifications apportées à votre logiciel, tout en assurant la rétro-compatibilité des sauvegardes des utilisateurs. Il suffit pour cela de définir deux méthodes dans la nouvelle version de la classe : une méthode d’instance nommée “binaryRpresentationVersion”, qui retourne la version de la classe (1, 2, 3… etc), et une méthode “binaryReaderBlockForVersion: oldVersion format: oldFormat” qui se charge de convertir l’anciene instance objet sous sa nouvelle forme. Le reste est fait automatiquement par BOSS.

BOSS est largement décrit dans le guide du développeur d’applications VisualWorks (AppDevGuide.pdf) situé dans le repertoire “doc” de votre installation VisualWorks. Ce billet en est d’ailleurs largement inspiré.

Avec un tel outils, imaginez la quantité de difficultés levées lors du developpement d’applications : sauvegarde aisée des éléments produits par l’applications, et mise à jour facile … Un bonheur.

Je crois (mais je n’en suis pas certain) qu’il est possible d’utiliser BOSS sur autre chose qu’un Stream sur un fichier. Une connexion TCP par exemple ? Je vérifierais, mais je n’ai pas encore en tête “l’application qui tue” d’une telle possibillité. Si vous avez des idées …

Tags :