I. Présentation▲
Algoid est un environnement de développement destiné à l'apprentissage de la programmation. Il vise un public de débutants très large ; de 10 à 20 ans.
Ce projet trouve sa source dans le programme Logo créé par Wally Feurzeig et Seymour Papert en 1967. Son fondement est identique ; un langage simplifié permet d'apprendre la programmation sur un principe visuel. Ce dernier permet de déplacer le curseur (la tortue) dessinant ainsi des formes géométriques.
Le langage de programmation prévu à cet effet se nomme AL (Algoid Language), il a été conçu comme un langage d'introduction aux langages professionnels. Comme son prédécesseur le Logo qui était inspiré du LISP pour en simplifier la syntaxe et les aspects techniques, AL est inspiré de langages tels que le Java, le JavaScript et le Python. AL simplifie un grand nombre de problématiques techniques de bas niveau comme le typage, la conversion, les types composites, l'instanciation des classes ou encore la gestion des événements. Avec le langage AL, ces aspects sont à la charge du langage et non du programmeur en herbe.
De plus, comme la syntaxe du langage est proche du Java et plus généralement du C, il est aisé de se convertir à des langages utilisés dans l'industrie après avoir appris sur Algoid.
Algoid se présente comme un « coup de jeune » au Logo, introduisant des notions plus modernes telles que la programmation orientée objet et aspect. Je pense que, ce qu'il est important d'apprendre, ce n'est pas la syntaxe d'un langage en particulier, mais les paradigmes qui induisent les façons de penser un programme.
AL a l'ambition de rendre l'apprentissage de ces paradigmes le plus progressif possible, mais aussi le plus complet.
Pour plus de précisions sur Algoid et ses fonctionnalités, consulter cet article.
II. Enseignement▲
Algoid est un environnement qui s'adresse aussi aux enseignants. Il leur permet d'étendre le logiciel, son langage et ses possibilités au gré des ateliers ou cours proposés.
Par exemple, si l'enseignant désire présenter des travaux pratiques sur la théorie des graphes, l'architecture à base de plugin d'Algoid lui permet de créer un IHM de représentation des graphes, ainsi que l'ensemble des objets et fonctions nécessaires à leur manipulation. Ainsi, il pourra animer son cours de façon interactive en illustrant les notions abordées et en faisant réaliser des scripts à ses élèves à partir des objets et fonctions qu'il aura créés. Il bénéficie ainsi de tout le travail déjà réalisé sur Algoid, son langage et son environnement.
II-A. Quelles sont les capacités des plugins ?▲
AL est un langage interprété, il a été écrit en Java. Il dispose d'un système complet d'états, de fonctions et d'objets qui constituent son API.
Cette API se concentre principalement sur l'acheminement de la petite tortue au centre de l'écran. Le langage et les capacités graphiques d'Algoid sont suffisamment étendus pour permettre au programmeur débutant de créer, entre autres, ses propres minijeux 2D, ou des moteurs 3D simples.
Les plugins permettent d'aller plus loin dans cette démarche tout en ayant une mise en œuvre simple (seulement deux classes sont nécessaires). Ils offrent la capacité d'étendre l'API. Pour cela il suffit d'ajouter les objets, les fonctions et les états nécessaires. Ces derniers seront chargés lors de l'exécution des programmes.
Facultativement, un plugin permet de créer une vue et de gérer des interactions avec la bibliothèque nouvellement créée au travers d'accesseurs et d'événements. Cette vue se présente sous forme d'un JPanel qui sera fourni par le plugin. Un JPanel permet de réaliser toute sorte d'IHM, basées sur des composants Swing.
Dès le chargement du plugin dans l'IDE, l'autocomplétion sera automatiquement mise à jour avec la nouvelle bibliothèque ! Si elle est renseignée par l'enseignant, la documentation interactive sera également devenue disponible.
II-B. Prérequis▲
La création d'un plugin pour Algoid doit être aussi simple que possible ! Cela ne demande que quelques connaissances de base du langage Java et des langages à objets. Des outils d'aide à la création des différents d'éléments de l'API (des factories) sont à disposition pour simplifier cette tâche.
Pour la réalisation de l'IHM (optionnelle), il est également nécessaire de posséder quelques connaissances de l'environnement graphique Swing de Java.
Le projet de création de plugin a été réalisé avec l'IDE Netbeans. L'IHM peut être dessinée grâce à l'outil WYSIWYG intégré à Netbeans, facilitant ainsi sa réalisation.
Pour ce faire, il est nécessaire de télécharger le projet, de le décompresser dans votre répertoire de travail et de l'ouvrir avec Netbeans. Les sources se trouvent également sur le portail de gestion de versions des sources bitbucket en accès libre.

III. Contenu du projet▲
Dès l'ouverture du plugin sous Netbeans, deux classes sont à disposition. C'est en les modifiant qu'il sera possible d'ajouter les fonctionnalités souhaitées.
PluginImplementation.java | Hérite de l'interface Plugin. Contient toutes les méthodes nécessaires à l'ajout d'entités au langage ainsi que les méthodes dynamiques, renseignements sur le plugin et chargement des ressources nécessaires. |
Panel.java | Optionnel, hérite de l'interface PluginPanel, elle décrit la vue additionnelle liée au plugin. |
La classe LaunchApplication.java sert uniquement à lancer l'IDE et le plugin préchargé afin de faciliter les tests nécessaires.
IV. Comment faire ?▲
La section qui suit s'articulera sous forme de questions/réponses.
IV-A. Comment fournir les renseignements liés au plugin ?▲
Pour identifier votre plugin, plusieurs renseignements sont nécessaires :
- le nom du plugin ;
- le nom de l'auteur ;
- la version ;
- la date de création.
Ces renseignements sont à fournir obligatoirement grâce à des méthodes templates disponibles dans l'interface Plugin.
Il suffit de les implémenter comme suit :
//
plugin
détails
@
Override
public
StringgetName
(){
//
nom
du
plugin
return
"
My
plugin
"
;}
@
Override
public
StringgetVersion
(){
//
version
du
plugin
return
"
0.0.1
(alpha)
"
;}
@
Override
public
StringgetAuthor
(){
//
nom
de
l'auteur
return
"
Yann
Caron
aka.
CyaNn
"
;}
@
Override
public
DategetCreationDate
(){
//
date
de
création
try
{
return
new
SimpleDateFormat
("
yyyy-MM-dd
"
, Locale.ENGLISH).parse
("
2013-09-03
"
);}
catch
(ParseException ex){
return
new
Date
();}
}
IV-B. Comment ajouter un objet à l'API ?▲
L'ajout d'éléments (à l'API, comme les états, fonctions et objets) s'effectue dans la méthode addFrameworkObjects de la classe plugin.
Pour simplifier cette création, la factory FactoryUtils est à disposition.
Créons un objet appelé « my »
ObjectDeclaration
<
RuntimeContext>
my=
FactoryUtils.createObject
(builder,"
my
"
);
La factory est responsable d'ajouter la définition de notre objet au builder. Builder est l'objet qui est en charge de traduire le script en mémoire afin de l'interpréter.
RuntimeContext est le contexte mémoire du langage contenant toutes les variables créées par le script.
Le type ObjectDeclaration décrit un objet en AL.
IV-C. Comment ajouter un état à notre objet « my » ?▲
Une fois notre objet créé, il est possible de lui ajouter plusieurs choses : des attributs, des attributs composites (array), des méthodes, des événements et des objets imbriqués.
Ajoutons un attribut de type string que l'on nommera « text » :
FactoryUtils.
addAttribute
(my,"
text
"
,"
this
is
my
text
"
);
L'attribut de type String, my.text est maintenant à la disposition de l'étudiant lorsqu'il écrira son script.
Après compilation du plugin, il faut lancer l'application avec le bouton run (le projet PluginAlgoIDE doit être sélectionné comme projet par défaut dans Netbeans).

Au démarrage, dans la console, l'application indique que le plugin a bien été chargé :
Plugin "My plugin v.0.0.1 (alpha)" created by Yann Caron aka. CyaNn the 2013-10-03 successfully loaded !
Testons maintenant notre objet et son attribut en saisissant la commande AL suivante :
util
.
log(
my.
text
)
;
Notons au passage que l'autocomplétion a pris en charge les nouveaux éléments de l'API que l'on vient de créer :

Après exécution du script, la console interne affiche bien la chaîne de caractères définie :

IV-D. Comment ajouter un tableau à notre objet « my » ?▲
Les états VOID, BOOLEAN, NUMBER et STRING possèdent tous une factory dédiée simplifiant leur création.
Pour ajouter un tableau, il est nécessaire de créer manuellement un MutableVariant. Cette classe décrit tous les types de données disponibles en AL. C'est ce mécanisme qui permet à AL de posséder un typage fort, implicite et néanmoins cohérent tout en limitant le nombre de transtypages.
Un MutableVariant peut lui-même jouer le rôle de liste (de MutableVariants), permettant de décrire des types composés complexes (types récursifs) ou un dictionnaire (liste associative).
Ajoutons un tableau à deux dimensions à notre objet « my » :
MutableVariant table
=
new
MutableVariant
();MutableVariant row1
=
new
MutableVariant
();row1.
add
(new
MutableVariant
("
row
1
col
1
"
));row1.
add
(new
MutableVariant
("
row
1
col
2
"
));row1.
add
(new
MutableVariant
("
row
1
col
3
"
));table.
add
(row1);MutableVariant row2
=
new
MutableVariant
();row2.
add
(new
MutableVariant
("
row
2
col
1
"
));row2.
add
(new
MutableVariant
("
row
2
col
2
"
));row2.
add
(new
MutableVariant
("
row
2
col
3
"
));table.
add
(row2);FactoryUtils.
addArray
(my,"
table
"
, table);
Cette écriture permet de créer un tableau qui sera ensuite disponible dans le langage AL sous cette forme :
row 1 col 1 | row 1 col 2 | row 1 col 3 |
row 2 col 1 | row 2 col 2 | row 2 col 3 |
Cela revient à écrire en AL le script suivant :
set
my=
object
(
)
{
set
table=
array
{
{
"
row
1
col
1
"
,
"
row
1
col
2
"
,
"
row
1
col
3
"
}
,
{
"
row
2
col
1
"
,
"
row
2
col
2
"
,
"
row
2
col
3
"
}
}
;
}
;
Que nous retrouvons sur Algoid comme suit :
ui
.
clearLog(
)
;
my
.
table.
eachItem(
function
(
item)
{
util
.
log(
item)
;
}
)
;
util
.
log(
my.
table)
;

IV-E. Comment ajouter une méthode à notre objet « my » ?▲
En AL, les fonctions, les tableaux et les objets sont des états comme les autres (ce qui confère au langage la faculté d'être fonctionnel, entre autres).
L'ajout d'une méthode s'effectue de la même manière que les attributs. Un objet de type Behaviour en fournira le comportement. Behaviour est basé sur la même idée que le Runnable fourni par Java, il permet de décrire un comportement.
Définissons une méthode de test qui se contente de créer une entrée dans le journal avec la combinaison d'un texte et d'un paramètre d'entrée.
FactoryUtils.
addMethod
(my,"
logTest
"
,new
FactoryUtils.Behaviour
(){
@
Override
public
void
visite
(Block<
RuntimeContext>
t, RuntimeContext c){
String name
=
FactoryUtils.getParam
(t,0
).getString
();//
get
parameter
appContext.
getLoggerPanel
().addLog
(AlgoIDEConstant.Severity.INFO,"
Log
test
[
"
+
name+
"
]
"
);}
}
,"
name
"
);
Pour ajouter des paramètres, il suffit de spécifier leurs noms en paramètre à la méthode addMethod([object], [name], [behaviour], [parameter1], [parameter2] ….)
La valeur des paramètres envoyés par l'utilisateur lors de l'exécution se récupère dans le behaviour grâce à la méthode FactoryUtils.getParam ([context], [id]).
Pour des raisons d'optimisation, les paramètres ne sont pas récupérés par leur nom, mais par leur indice d'entrée (0, 1, 2…). Par souci de lisibilité, nous utiliserons comme nom de variable, le même que celui du paramètre visé. Comme ici où nous avons utilisé name comme nom de variable.
La méthode getParam renvoie un MutableVariant qui dispose des méthodes nécessaires à l'acquisition des valeurs en Java : getString, getNumber etc.
La méthode appContext donne accès à toutes les ressources internes de l'IDE :
appContext.getAlgoPanel () | Le panel Algo (la petite tortue). |
appContext.getIDEPanel () | Le champ texte de saisie du code source. |
appContext.getInvitePanel () | Le panel Invite de saisie utilisateur lors de l'exécution. |
appContext.getLoggerPanel () | Le journal et son fichier de journalisation. |
appContext.getTaskManager () | L'objet en charge de gérer l'exécution des tâches, des événements, etc. C'est le « thread » d'exécution du script. |
Voici notre méthode à l'œuvre :
my
.
logTest(
"
the
test
"
)
;

IV-F. Comment ajouter une méthode à un objet existant dans l'API ?▲
De la même façon qu'une méthode classique, mais en récupérant l'instance de l'objet avec la méthode FactoryUtils.findObject().
ObjectDeclaration
<
RuntimeContext>
algo=
FactoryUtils.findObject
(builder,"
algo
"
);FactoryUtils.
addMethod
(algo,"
logTest
"
,new
FactoryUtils.Behaviour
(){
@
Override
public
void
visite
(Block<
RuntimeContext>
t, RuntimeContext c){
appContext.
getLoggerPanel
().addLog
(AlgoIDEConstant.Severity.INFO,"
method
successfully
added
to
algo
and
log
test
OK
!
"
);}
}
);
IV-G. Comment ajouter une méthode dynamique ?▲
En AL, une méthode dynamique est une méthode qui est ajoutée dynamiquement (lors de la phase d'exécution du script) à un type primitif du langage. C'est la même notion que les « magics methods » dans le langage Python.
Les méthodes dynamiques s'ajoutent dans la méthode addDynamicMethods de l'objet plugin ; la factory FactoryUtils.addMagicMethod facilite sa création.
Voici un exemple où l'on ajoute la méthode « plus » aux types primitifs NUMBER.
FactoryUtils.
addMagicMethod
(context, dynamicMethods, Types.NUMBER,"
plus
"
,new
FactoryUtils.Behaviour
(){
@
Override
public
void
visite
(Block<
RuntimeContext>
ast, RuntimeContext context){
MutableVariant self
=
ast.function.self.mv;FunctionInstance f
=
ast.function;float
operand=
f.decl.params.get
(0
).var.mv.getNumber
();//
return
context.
returnValue
(self.getNumber
()+
operand);}
}
,"
operand
"
);
Qui sera utilisé comme ceci dans un script Algoid :
set i
=
7
;util.log (i.plus (
20
));

Les méthodes dynamiques peuvent être définies pour tous les types primitifs du langage : VOID, BOOL, NUMBER, STRING, ARRAY, FUNCTION, OBJECT.
Une méthode ainsi ajoutée au type OBJET revient à ajouter la méthode à tous les objets du langage, même les objets préexistants sans que leur définition initiale n'ait été changée. En cas de conflit, ce sera la dernière méthode ajoutée qui surchargera les autres.
IV-H. Comment créer une nouvelle vue ?▲
La vue est définie dans la classe Panel.java qui hérite de la super classe PluginPanel.
Cette classe doit impérativement spécifier son nom dans son constructeur :
*
/
public
class
Panelextends
PluginPanel{
public
Panel
(){
super
("
my
panel
"
);//
nom
obligatoire
initComponents
();}
}
Lors du chargement du plugin par l'application, un nouvel onglet contenant notre vue sera créé.

La création se fait ensuite comme la création de n'importe quel JPanel en Swing.
Algoid ne définit qu'une vue par plugin. Il est toutefois possible d'ajouter une vue composée (avec l'aide des classes JTabbedPane et JSplitePane).
Le panel doit ensuite être construit dans la méthode « initialize » de notre plugin :
//
the
additional
panel
private
Panel myPanel;//
initialize
ressources
here
@
Override
public
void
initialize
(){
myPanel
=
new
Panel
();}
Puis être fourni par la méthode getAdditionalPanel de notre plugin :
@
Override
public
PluginPanelgetAdditionalPanel
(){
return
myPanel;}
Dans le cas où le plugin ne définit pas de panel additionnel, il suffit de renvoyer la valeur null dans la méthode getAdditionalPanel.
IV-I. Comment accéder aux composants de la vue ?▲
Pour accéder aux valeurs des composants de la vue, deux choses très simples doivent être définies :
- une méthode publique d'accès à la valeur (par exemple getFieldText) ;
- l'ajout d'une méthode à notre objet dans le langage AL.
Voici par exemple les méthodes d'accès au champ « text » de notre panel (défini dans le fichier panel.java) :
public
void
setFieldText
(String text){
fld_my.
setText
(text);}
public
StringgetFieldText
(){
return
fld_my.getText
();}
Ces méthodes seront ensuite utilisées pour définir les méthodes de notre objet « my » dans l'API du langage AL (fichier PluginImplementation.java) :
//
getter
method
FactoryUtils.
addMethod
(my,"
getFieldText
"
,new
FactoryUtils.Behaviour
(){
@
Override
public
void
visite
(Block<
RuntimeContext>
t, RuntimeContext c){
String text
=
myPanel.getFieldText
();c.
returnValue
(text);//
return
the
value
of
field
}
}
);//
setter
method
FactoryUtils.
addMethod
(my,"
setFieldText
"
,new
FactoryUtils.Behaviour
(){
@
Override
public
void
visite
(Block<
RuntimeContext>
t, RuntimeContext c){
String text
=
FactoryUtils.getParam
(t,0
).getString
();//
get
the
text
parameter
string
value
myPanel.
setFieldText
(text);}
}
,"
text
"
);
Voici ce que cela donne au sein d'Algoid ; le script peut modifier les données contenues dans les contrôles de notre nouvelle vue.

IV-J. Comment assigner un événement au panel ?▲
Comme vu précédemment pour les accesseurs, pour créer un événement, il faut créer la méthode publique qui permet d'ajouter l'événement dans le panel (fichier Panel.java).
public
void
addButtonActionListener
(ActionListener listener){
btn_my.
addActionListener
(listener);}
Puis de créer une façade à cette méthode dans l'API du langage AL (fichier PluginImplementation.java).
//
event
method
FactoryUtils.
addMethod
(my,"
onClick
"
,new
FactoryUtils.Behaviour
(){
@
Override
public
void
visite
(Block<
RuntimeContext>
t,final
RuntimeContext c){
final
FunctionInstance f=
FactoryUtils.getParam
(t,0
).getFunction
();//
get
the
call
back
function
!
//
register
to
button
action
listener
myPanel.
addButtonActionListener
(new
ActionListener
(){
@
Override
public
void
actionPerformed
(ActionEvent e){
//
create
callback
parameter
to
send
MutableVariant text
=
new
MutableVariant
(myPanel.getFieldText
());//
call
callback
with
parameters
(if
necessary)
appContext.
callFunction
(c, f, text);}
}
);}
}
,"
f
"
);
La méthode onClick est responsable d'ajouter le listener d'événements à notre panel. Le listener contiendra le comportement à exécuter à chaque clic de l'utilisateur.
Dans notre cas, il récupère la valeur du champ texte et invoque la fonction de callback spécifiée par l'utilisateur. Cette méthode sera exécutée grâce à la fonction appContext.callFunction.
La fonction de callBack a été récupérée comme tout état du langage par la méthode FactoryUtils.getParam().getFunction().
Voici comment utiliser notre événement dans le langage AL :
my
.
onClick(
function
(
text
)
{
util
.
log(
"
User
entry
:
"
..
text
)
;
}
)
;

IV-K. Comment créer une méthode pour afficher le panel?▲
Comme toute méthode :
FactoryUtils.
addMethod
(my,"
show
"
,new
FactoryUtils.Behaviour
(){
@
Override
public
void
visite
(Block<
RuntimeContext>
t, RuntimeContext c){
appContext.
getIDEPanel
().showPanel
(myPanel.getName
());}
}
);
Cette méthode doit appeler la fonction showPanel de l'IDE grâce à appContext.getIDEPanel().showPanel([nom du panel]).
V. Installation▲
Maintenant que le plugin est prêt, il reste à l'installer dans notre logiciel préféré.
Pour ce faire, il suffit de faire un « clean and build » dans Netbeans (cette action compile le code source et crée une archive exécutable .jar) et de copier le jar obtenu ([project]/dist/PluginAlgoIDE-package.jar) dans le répertoire plugin se situant à la racine de l'installation du programme.
Par exemple, si votre AlgoIDE est installé comme suit :
c:\program files\algoid\AlgoIDE.jar
Il vous faudra créer les répertoires suivants :
c:\program files\algoid\plugins
Et y copier le jar :
c:\program files\algoid\plugins\PluginAlgoIDE-package.jar
Le jar PluginAlgoIDE-package.jar contient les classes Java ainsi que toutes les bibliothèques nécessaires à son exécution.
Lors du lancement d'AlgoIDE, vérifiez que le plugin est correctement installé. Une ligne doit l'indiquer dans la console au démarrage de l'application.
Plugin "
My
plugin
v
.
0
.
0
.
1
(
alpha
)
"
created by Yann Caron aka. CyaNn the 2013
-09
-03
successfully loaded !
Il est conseillé de renommer le jar avant sa copie dans le répertoire plugins de façon à ce que plusieurs plugins puissent coexister. Il est possible d'automatiser cette tâche en modifiant le nom du jar dans le script ant build.xml (se référer à la documentation).
VI. Quelques idées de plugins▲
Nous venons de voir l'étendue des capacités des plugins pour Algoid et comment les réaliser avec des exemples simples.
Après un sondage des utilisateurs, voici quelques suggestions de plugins qui seraient utiles à Algoid :
- l'étude de la théorie des graphes avec une bibliothèque de création et de lecture des graphes ;
- l'étude de l'électronique grâce à une bibliothèque qui donne accès au GPIO sous Raspberry PI ;
- Mindstorm communication : un protocole de communication pour piloter les robots NXT permettant une étude de la robotique ;
- un environnement de création de jeu 2d (gestion des sprites, des animations, des maps 2d, des collisions…) ;
- ajouter la gestion du son à Algoid ;
- un scénographe 3d ;
- ALON (Algoid Language Object Notation) un équivalent de JSON pour sérialiser les objets AL et les stocker sur le disque ou communiquer via le réseau ;
- une gestion de base de données ;
- la création de HMI à base de script AL.
Alors, si vous souhaitez participer au projet Algoid ou tout simplement l'utiliser dans le cadre de formations spécifiques, n'hésitez pas à y ajouter vos propres plugins et à les partager pour que tout le monde puisse en profiter.
VII. Remerciements▲
Je tiens à remercier toute ma petite famille qui ferme les yeux sur ma geek attitude et me pardonne mon manque de présence… Du moins parfois.
Tout particulièrement mon fiston Tony de 12 ans qui m'a inspiré cette belle aventure le jour où il m'a posé la question suivante : « Papa, c'est quoi la programmation ? »
Merci également à toute l'équipe du forum developpez.com pour leurs lectures patientes, leurs corrections (plus que patientes) et leurs encouragements très appréciés. Tout particulièrement Feanorin et Thierry Leriche Dessirier pour leur relecture technique avisée et Claude Leloup pour ses promptes corrections orthographiques.
Vos retours nous aident à améliorer nos publications. N'hésitez donc pas à commenter cet article sur le forum : 3 commentaires
VIII. Annexes▲
Voici un exemple complet AL d'utilisation de notre plugin :
ui
.
clearLog(
)
my
.
show(
)
my
.
logTest(
)
algo
.
logTest(
)
my
.
setFieldText(
"
random
"
..
math
.
random(
100
)
)
util
.
log(
"
my.text
=
'
"
..
my.
getFieldText(
)
..
"
'
"
)
my
.
onClick(
function
(
text
)
{
util
.
log(
"
button
clicked
with
param:
'
"
..
text
..
"
'
"
)
}
)
VIII-A. Colophon▲
Retrouvez tout l'univers d'Algoid, la référence, les tutoriels et bien d'autres sur http://caron.yann.free.fr/algoid.
Retrouvez ma page et mes autres articles sur Developpez.com à l'adresse
http://caron-yann.developpez.com
Suivez-moi sur Google+ : https://plus.google.com/103229648308320817267/posts