[JAVA] Mémo d'utilisation PlantUML

Comme il sera long, vous ne pouvez dessiner le diagramme qu'avec le diagramme de classes et le diagramme de séquence.

Qu'est-ce que PlantUML

--Un type de DSL qui vous permet d'écrire des diagrammes UML dans du texte (probablement)

Environnement

Le système d'exploitation est Windows 10.

Java

> java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)

La méthode d'installation est omise.

Corps PlantUML

https://plantuml.com/ja/download

Déposez plantuml.jar d'ici. Au moment de la confirmation, il s'agissait de «plantuml.1.2020.7.jar».

Graphviz http://www.graphviz.org/download/

Cela ressemble au logiciel utilisé pour dessiner la figure. Graphviz - Wikipedia

Il est pratiquement nécessaire car il est nécessaire si vous souhaitez générer des diagrammes autres que des diagrammes de séquence et des diagrammes d'activités **.

J'ai laissé tomber "2.38".

Spécifiez l'emplacement de dot.exe

Lorsque vous exécutez PlantUML, vous devez spécifier l'emplacement de dot.exe dans Graphviz. La méthode de désignation est l'une des suivantes (classée par ordre de priorité à adopter).

  1. Spécifiez avec l'option -graphvizdot
  2. Spécifiez dans la propriété système GRAPHVIZ_DOT
  3. Définissez la variable d'environnement GRAPHVIZ_DOT

Si le dossier dans lequel Graphviz est installé est C: \ Graphviz, spécifiez-le comme suit.

-Lorsqu'il est spécifié avec l'option graphvizdot


> java -jar plantuml.jar -graphvizdot C:\Graphviz\bin\dot.exe ...

Lorsque spécifié dans les propriétés système


> java -DGRAPHVIZ_DOT=C:\Graphviz\bin\dot.exe -jar plantuml.jar ...

Lorsqu'il est spécifié par la variable d'environnement


> set GRAPHVIZ_DOT
GRAPHVIZ_DOT=C:\Graphviz\bin\dot.exe

VSCode Lorsque vous utilisez les plug-ins suivants, définissez la variable d'environnement GRAPHVIZ_DOT avant d'exécuter VSCode.

PlantUML PlantUML - Visual Studio Marketplace

plantuml.jpg

Markdown Preview Enhanced Markdown Preview Enhanced - Visual Studio Marketplace

--Un plug-in qui vous permet de prévisualiser PlantUML dans Markdown

plantuml.jpg

Hello World

hello.pu


@startuml
Hello <|-- World
@enduml

--Créez un fichier texte et décrivez le contenu comme ↑

Courir


> java -jar plantuml.jar hello.pu

--Spécifiez le fichier texte créé comme argument et exécutez --Ensuite, un fichier appelé hello.png sera généré au même emplacement que le fichier spécifié par l'argument.

hello.png

hello.png

Comment exécuter à partir de la ligne de commande

Spécification du fichier

> dir /b
fuga.pu
hoge.pu
piyo.pu

> java -jar plantuml.jar hoge.pu fuga.pu piyo.pu

> dir /b
fuga.png
fuga.pu
hoge.png
hoge.pu
piyo.png
piyo.pu

--Peut être exécuté en spécifiant le chemin du fichier comme argument --Plusieurs fichiers peuvent être spécifiés

Spécification d'annuaire

Structure des dossiers


`-hoge/
  |-plantuml.pu
  |-markdown.md
  |-JavaSource.java
  `-fuga/
    `-fuga.pu

plantuml.pu

@startuml
class PlantUml
@enduml

markdown.md

```
@startuml
class Markdown
@enduml
```

JavaSource.java

/**
 * @startuml
 * class JavaSource {
 *   - String message
 * }
 * @enduml
 */
public class JavaSource {}

fuga.pu

@startuml
class Fuga
@enduml

Courir

> java -jar plantuml.jar hoge

Après exécution


`-hoge/
  |-plantuml.pu
  |-plantuml.png
  |-markdown.md
  |-JavaSource.java
  |-JavaSource.png
  `-fuga/
    `-fuga.pu

--plantuml.png et JavaSource.png ont été générés

plantuml.png

plantuml.png

JavaSource.png

JavaSource.png

Spécifiez avec un caractère générique

> java -jar plantuml.jar "hoge/**"

--La partie où le dossier est spécifié est définie sur `` hoge / ** "`

Résultat d'exécution


`-hoge/
  |-plantuml.pu
  |-plantuml.png
  |-markdown.md
  |-markdown.png
  |-JavaSource.java
  |-JavaSource.png
  `-fuga/
    |-fuga.pu
    `-fuga.png

--markdown.png et fuga.png sont également générés

markdown.png

mardown.png

fuga.png

fuga.png

Spécifiez la cible d'exclusion

> java -jar plantuml -x "**/*.pu" "hoge/**"

Résultat d'exécution


`-hoge/
  |-plantuml.pu
  |-markdown.md
  |-markdown.png
  |-JavaSource.java
  |-JavaSource.png
  `-fuga/
    `-fuga.pu

Spécification du code de caractère

> java -jar plantuml.jar -charset UTF-8 hello.pu

--Le code de caractère est spécifié avec l'option -charset

Lire à partir de l'entrée standard

> type plantuml | java -jar plantuml.jar -pipe > result.png

--Si l'option -pipe est spécifiée, elle sera lue à partir de l'entrée standard, donc les tubes seront possibles.

Lorsqu'il y a plusieurs descriptions de figures

hoge.pu


@startuml
class Hoge
@enduml

@startuml
class Fuga
@enduml

@startuml
class Piyo
@enduml

--Quand il y a plusieurs descriptions @startuml ... @ enduml dans un fichier

Courir


> java -jar plantuml.jar hoge.pu

Résultat d'exécution


> dir /b
hoge.png
hoge.pu
hoge_001.png
hoge_002.png

hoge.png

hoge.png

hoge_001.png

hoge_001.png

hoge_002.png

hoge_002.png

Spécifiez le nom de fichier pour chaque figure

hoge.pu


@startuml hoge
class Hoge
@enduml

@startuml fuga
class Fuga
@enduml

@startuml piyo
class Piyo
@enduml

Courir


> java -jar plantuml.jar hoge.pu

Résultat d'exécution


> dir /b
fuga.png
hoge.png
hoge.pu
piyo.png

hoge.png

hoge.png

fuga.png

fuga.png

pioy.png

piyo.png

Voir aide

> java -jar plantuml.jar -h

Commun

commentaire

@startuml no-scale
'Ceci est un commentaire
Hello <|-- World
@enduml

--De guillemet simple (`` ''), le reste est traité comme un commentaire

Titre

@startuml
title Hello Title
Hello <|-- World
@enduml

hoge.png

Titre sur plusieurs lignes

@startuml
title
Hello
Title
end title
Hello <|-- World
@enduml

hoge.png

Écrire dans un langage de balisage

@startuml
title
* __Hello__
* **World**
end title
Hello <|-- World
@enduml

hoge.png

légende

@startuml
légende Figure 1
Hello <|-- World
@enduml

hoge.png

en-tête pied de page

@startuml
header Hello
Hello <|-- World
footer World
@enduml

hoge.png

Précisez la position

@startuml
left header Hello
Hello <|-- World
right footer World
@enduml

hoge.png

Écrivez sur plusieurs lignes

@startuml
header
Hello
Header
end header

Hello <|-- World

footer
World
Footer
end footer
@enduml

hoge.png

Guide d'utilisation

@startuml
legend
Hello World
end legend

Hello <|-- World
class FizzBuzz
@enduml

hoge.png

Précisez la position

@startuml right
legend right
Right
end legend

Hello <|-- World
class FizzBuzz
@enduml

right.png

--Si vous ne spécifiez que les positions gauche et droite, les positions supérieure et inférieure seront les positions par défaut «bas».

@startuml top
legend top
Top
end legend

Hello <|-- World
class FizzBuzz
@enduml

top.png

--Si vous ne spécifiez que les positions supérieure et inférieure, les positions gauche et droite seront le centre par défaut.

@startuml top-left
legend top left
Top Left
end legend

Hello <|-- World
class FizzBuzz
@enduml

top-left.png

--Si les deux sont spécifiés, ils seront affichés à la position spécifiée.

Taux d'expansion

@startuml no-scale
Hello <|-- World
@enduml

@startuml scale-1.5
scale 1.5
Hello <|-- World
@enduml

@startuml scale-0.5
scale 0.5
Hello <|-- World
@enduml

plantuml.jpg

Creole

@startuml
note left
  --Titre--
  =Titre 1
  ==Titre 2
  ===Titre 3
  
  --Liste non numérotée--
  *Liste 1
  *Liste 2
  **Annonce 2-1
  *Liste 3

  --Numéroté--
  #Liste numérotée 1
  #Liste numérotée 2
  ##Liste numérotée 2-1
  #Liste numérotée 3

  --Décoration--
  * **Audacieux**
  * //italique//
  * ""Police de largeur égale(monospace)""
  * --Ligne d'annulation--
  * __Souligner__

  --table--
  |= |= Column1 |= Column2 |
  |1 |Value1-1  |Value1-2  |
  |2 |Value2-1  |Value2-2  |

  --HTML--
  * <color:red>Spécification du nom de couleur</color>
  * <color:#00FF00>Spécification du code couleur</color>
  * <back:skyblue>Couleur de l'arrière plan</back>
  * <size:18>taille de police</size>
  * <b>Audacieux</b>

  --Structure arborescente--
  |_build.gradle
  |_src
    |_main
      |_java
        |_**bold**
        |_--strike--
        |_//itaric//
        |___underline__
        |_""monospace""
    |_test

  --Unicode--
  * <U+20BB7>

  --Escape--
  * **Ce sera audacieux**
  * ~**Cela ne devient pas audacieux**

  --Horizon--
  --Insérez le titre--
  ----
  ==Insérez le titre==
  ====
  ..Insérez le titre..
  ....
end note
@enduml

hoge.png

Spécifiez la police

@startuml
skinparam DefaultFontName Meilio
Bonjour<|--monde
@enduml

hoge.png

> java -jar plantuml.jar -language
...
;skinparameter
;536
ActivityBackgroundColor
ActivityBarColor
ActivityBorderColor
ActivityBorderThickness
ActivityDiamondBackgroundColor
ActivityDiamondBorderColor
ActivityDiamondFontColor
...

Diagramme de classe

Déclarer une classe

@startuml
class Hello
class World
@enduml

hoge.png

Déclarer l'interface

@startuml
interface Hello
interface World
@enduml

hoge.png

Déclarer une classe abstraite

@startuml
abstract class Hello
@enduml

hoge.png

Déclarer enum

@startuml
enum HelloWorld {
    ONE
    TWO
    THREE
}
@enduml

hoge.png

Décrire les relations entre les types

Liens connexes)

@startuml
Hello -- World
@enduml

hoge.png

Expression de l'inductibilité

@startuml
class One
One --> Two
Three <-- Four
Five <--> Six
Seven x-- Eight
Nine --x Ten
@enduml

hoge.png

--L'inductibilité peut être exprimée par «<», «>», «x».

Dépendance

@startuml
One ..> Two
Three <.. Four
@enduml

hoge.png

Généralisation

@startuml
One --|> Two
Three <|-- Four
@enduml

hoge.png

La concrétisation

@startuml
One ..|> Two
Three <|.. Four
@enduml

hoge.png

Agrégation

@startuml
One --o Two
Three o-- Four
@enduml

hoge.png

Composition

@startuml
One --* Two
Three *-- Four
@enduml

hoge.png

--La composition peut être exprimée par - *, * -

Nom associé

@startuml
One -- Two : Hoge
Three -- Four : Fuga >
Five -- Six : < Piyo
@enduml

hoge.png

--Si vous mettez : après la relation, vous pouvez écrire le nom de la relation après. --En mettant <, > avant et après le nom associé, vous pouvez exprimer la direction du

Nom du rôle et multiplicité

@startuml
One "Foo" -- Two 
Three -- "Bar" Four
Five "1" -- "1..*" Six
Seven "1 Fizz" -- "~* Buzz" Eight
@enduml

hoge.png

Définition de la méthode de terrain

@startuml
class Hello {
    one: String
    three(param1: String, param2: int): boolean
    String two
    int four(List<String> param)
}
@enduml

hoge.png

--Les champs et les méthodes peuvent être déclarés à l'intérieur de class <type name> suivi de crochets ondulés ({...}). --Peut être écrit non seulement dans la description formelle comme UML (nom de champ: nom de type) mais aussi en écriture de type Java ( nom de champ de nom de type) ――Il semble que vous puissiez écrire n'importe quoi, mais je pense qu'il est prudent d'utiliser la notation UML officielle.

Visibilité

@startuml
class Hello {
    - privateField: int
    # protectedField: int
    ~ packagePrivateField: int
    + publicField: int

    - privateMethod(): void
    # protectedMethod(): void
    ~ packagePrivateMethod(): void
    + publicMethod(): void
}
@enduml

hoge.png

--Si vous décrivez la visibilité en notation UML, ce sera un affichage d'icônes dédié

@startuml
skinparam classAttributeIconSize 0
class Hello {
    - privateField: int
    # protectedField: int
    ~ packagePrivateField: int
    + publicField: int

    - privateMethod(): void
    # protectedMethod(): void
    ~ packagePrivateMethod(): void
    + publicMethod(): void
}
@enduml

hoge.png

--Lorsque skinparam classAttributeIconSize 0 est défini, l'affichage de l'icône de visibilité disparaît.

Membre abstrait

@startuml
class Hello {
    {abstract} one: int
    {abstract} two(): int
}
@enduml

hoge.png

Membre statique

@startuml
class Hello {
    {static} ONE: int
    {static} two(): int
}
@enduml

hoge.png

Stéréotype

@startuml
class Hello <<Hoge>>
class World <<Fuga>> {
    message: String
}
@enduml

hoge.png

modèle

@startuml
class Hello<H>
class World<W> <<Hoge>>
@enduml

hoge.png

Écrire des réalisations et des généralisations comme du code Java

@startuml
interface One
interface Two
interface Three extends Two
interface Four
class Five implements One, Three
class Six extends Five implements Four {
    field: String
    method(): void
}
@enduml

hoge.png

paquet

@startuml
package one.two {
    class Hello
}

package three.four {
    World -- Hello
}
@enduml

hoge.png

Faites attention à l'ordre de déclaration

Lorsque l'ordre de déclaration de colis est inversé


@startuml
package three.four {
    World -- Hello
}

package one.two {
    class Hello
}
@enduml

hoge.png

Remarque

@startuml
class Fizz
note left: fizz

class Buzz
note right: buzz

class Foo
note top: foo

class Bar
note bottom: bar
@enduml

hoge.png

-Derrière la déclaration de classe etc.note <top|bottom|left|right>: <commentaire>En écrivant, vous pouvez écrire une note pour l'élément immédiatement précédent.

Spécifiez l'élément auquel attacher une note

@startuml
Fizz -- Buzz
note left of Fizz: fizz
note right of Buzz: buzz
@enduml

hoge.png

--note <position> de <target>: En écrivant <comment> , vous pouvez ajouter une note à l'élément spécifié par <target>.

Prendre des notes sur les associations

@startuml
Fizz -- Buzz
note on link: fizz-buzz
note left: buzz
@enduml

hoge.png

Donnez un nom à la note

@startuml
note "Hello World" as n1
Hello -- n1
World .. n1

note "Fizz Buzz" as n2
@enduml

hoge.png

Rédiger des notes sur plusieurs lignes

@startuml
class Hello
note left
Hello
World
end note

Fizz -- Buzz
note on link
Fizz
Buzz
end note
note left of Fizz
fizz
buzz
end note

note as n1
Foo
Bar
end note
@enduml

hoge.png

Diagramme de séquençage

Message de synchronisation

@startuml
Alice -> Bob: Hi
Bob --> Alice: Hi

Alice -> Bob: Is this a pen?
Bob --> Alice: No! This is an apple!!
@enduml

hoge.png

Message asynchrone

@startuml
Alice ->> Bob: Hi
Alice ->> Bob: Is this a pen?
Alice ->> Bob: Is this a pen??
Alice ->> Bob: Is this a pen???
Alice ->> Bob: Is this a pen????

Bob -> Alice: This is an apple!!!
@enduml

hoge.png

Spécifiez l'ordre des lignes de vie

@startuml
participant Alice
participant Bob
participant Carol

Carol -> Bob: Is the tip included?
Bob -> Alice:Serez-vous capable de dépasser Teppen un jour?
@enduml

hoge.png

--Si vous ne faites rien, les lignes de vie seront disposées à partir de la gauche dans l'ordre dans lequel elles apparaissent du haut. --Si vous souhaitez spécifier l'ordre des lignes de vie, définissez une séquence distincte sous la forme de paritcipant <nom de la ligne de vie>.

Utiliser des icônes pour les lignes de vie

@startuml
actor Actor
boundary Boundary
control Control
entity Entity
database Database
collections Collections
@enduml

hoge.png

Message à moi-même

@startuml
Aclie -> Aclie:Ne t'enfuis pas
Aclie -> Aclie:Ne t'enfuis pas
Aclie -> Aclie:Ne t'enfuis pas
Aclie -> Aclie:Ne t'enfuis pas
Aclie -> Aclie:Ne t'enfuis pas
@enduml

hoge.png

Nombre de messages

@startuml
Alice -> Bob: Hi
autonumber
Bob -> Carol: Hi
Carol -> Dave: Hi
Bob -> Dave: Hi
@enduml

hoge.png

Spécifiez le numéro de départ et l'incrément

@startuml
autonumber 3
Alice -> Bob: Hi
Bob -> Carol: Hi
autonumber 2 3
Carol -> Dave: Hi
Bob -> Dave: Hi
@enduml

hoge.png

Pause / reprise de la numérotation automatique

@startuml
autonumber
Alice -> Bob: Hi
autonumber stop
Bob -> Carol: Hi
Carol -> Dave: Hi
autonumber resume
Bob -> Dave: Hi
Carol -> Dave: Hi
@enduml

hoge.png

Regroupement de messages

@startuml
Alice -> Bob: Is this a pen?
alt yes
    Alice <-- Bob: Yes! This is a pen!!
else no
    Alice <-- Bob: Noooooooo! This is an apple!!!!!
end
@enduml

hoge.png

Lorsqu'il est imbriqué


@startuml
Alice -> Bob: Is this a pen?
alt yes
    Alice <-- Bob: Yes! This is a pen!!
else no
    Alice <-- Bob: Noooooooo! This is an apple!!!!!
    loop ∞
        Alice -> Bob: Oh sorry! By the way, is this a pen?
        Alice <-- Bob: Noooooooooooooooooo!!!!
    end
end
@enduml

hoge.png

Créer un groupe avec n'importe quel nom

@startuml
copie de groupe
    Alice -> Bob: Is this a pen?
    Alice <-- Bob: No! This is an apple!!
end
@enduml

hoge.png

Spécifications d'exécution

@startuml
activate Alice
Alice -> Bob

activate Bob
Bob -> Carol

activate Carol
Bob <-- Carol

deactivate Carol
Alice <-- Bob

deactivate Bob
@enduml

hoge.png

--ʻActivate `peut exprimer la spécification d'exécution de la ligne de vie avec le nom spécifié.

Nid

@startuml
activate Alice
Alice -> Bob

activate Bob
Bob -> Bob
activate Bob
Bob -> Carol

activate Carol
Bob <-- Carol

deactivate Carol
Alice <-- Bob

deactivate Bob
@enduml

hoge.png

Génération de ligne de vie

@startuml
Alice -> Bob
create Carol
Bob -> Carol: new
Bob -> Carol
Bob <-- Carol
Alice <-- Bob
@enduml

hoge.png

référence

@startuml
Alice -> Bob
ref over Bob, Carol:Voir là-bas
Alice <-- Bob
ref over Alice
Là bas
référence
end ref
@enduml

hoge.png

frontière

@startuml
== Foo ==
Alice -> Bob
Alice <-- Bob

== Bar ==
Bob -> Carol
Bob <-- Carol
@enduml

hoge.png

Message de l'extérieur

@startuml
[-> Alice: Hello
Alice ->]: Hello
@enduml

hoge.png

--En utilisant [, ] au lieu du nom de la ligne de vie, vous pouvez écrire un message de l'extérieur (vers)

Espacement entre les messages

@startuml
Alice -> Bob
Alice <-- Bob

Alice -> Bob
Alice <-- Bob
|||
Alice -> Bob
Alice <-- Bob
||80||
Alice -> Bob
Alice <-- Bob
@enduml

hoge.png

-Entre les messages|||Vous pouvez laisser un peu d'espace en sandwich

Remarque

@startuml
Alice -> Bob
note left: Hello
Alice <-- Bob
note right: World
Alice -> Alice
note left
Hello
World
end note
@enduml

hoge.png

Utilisation depuis Java

Spécification Graphviz

Spécification de dépendance

build.gradle


plugins {
    id "application"
}

sourceCompatibility = 11
targetCompatibility = 11
compileJava.options.encoding = "UTF-8"

mainClassName = "sandbox.plantuml.Main"

repositories {
    mavenCentral()
}

dependencies {
    implementation "net.sourceforge.plantuml:plantuml:8059"
}

-Ajouter net.sourceforge.plantuml: plantuml à la dépendance

Lire à partir de la source String

Main.java


package sandbox.plantuml;

import net.sourceforge.plantuml.SourceStringReader;

import java.io.File;

public class Main {

    public static void main(String[] args) throws Exception {
        String source = "@startuml\n"
                      + "Foo <-- Bar\n"
                      + "@enduml";
        final SourceStringReader reader = new SourceStringReader(source);
        reader.generateImage(new File("result.png "));
    }
}

Résultat d'exécution


> gradle run
...

result.png

Lorsque plusieurs images sont définies

Main.java


package sandbox.plantuml;

import net.sourceforge.plantuml.SourceStringReader;

import java.io.FileOutputStream;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) throws Exception {
        String source = "@startuml FooBar\n"
                      + "Foo <-- Bar\n"
                      + "@enduml\n"
                      + "\n"
                      + "@startuml FizzBuzz\n"
                      + "Fizz <-- Buzz\n"
                      + "@enduml";
        final SourceStringReader reader = new SourceStringReader(source);
        try (
            OutputStream fooBar = new FileOutputStream("foobar.png ");
            OutputStream fizzBuzz = new FileOutputStream("fizzbuzz.png ");
        ) {
            reader.generateImage(fooBar, 0);
            reader.generateImage(fizzBuzz, 1);
        }
    }
}

Lire à partir du fichier source

Structure des dossiers


|-source.pu
|-build.gradle
`-src/main/java/
  `-sandbox/plantuml/
    `-Main.java

source.pu


@startuml FooBar
Foo <-- Bar
@enduml

@startuml FizzBuzz
Fizz <-- Buzz
@enduml

――Deux chiffres sont définis

Main.java


package sandbox.plantuml;

import net.sourceforge.plantuml.SourceFileReader;

import java.io.File;

public class Main {

    public static void main(String[] args) throws Exception {
        final SourceFileReader reader = new SourceFileReader(new File("source.pu"));
        reader.getGeneratedImages();
    }
}

--Lecture du fichier source avec SourceFileReader --Lorsque vous exécutez getGeneratedImages (), des images sont générées.

Résultat d'exécution


> gradle run
...

Structure des dossiers


|-source.pu
|-FooBar.png
|-FizzBuzz.png
|-build.gradle
`-src/main/java/
  `-sandbox/plantuml/
    `-Main.java

FooBar.png FooBar.png

FizzBuzz.png FizzBuzz.png

référence

Recommended Posts

Mémo d'utilisation PlantUML
Notes d'utilisation de JavaParser
Notes d'utilisation de WatchService
Notes d'utilisation de JUnit5
Notes d'utilisation de Spring Shell
Mémo d'utilisation de Spring Security CSRF
Mémo d'utilisation de Spring Security Run-As
Spring Security Usage Memo Method Security
Mémo d'utilisation de Spring Security Remember-Me
Notes sur l'utilisation du plug-in de gestion des dépendances
Mémo d'utilisation de Spring Security CORS
Test de mémo d'utilisation de Spring Security
Authentification / autorisation de mémo d'utilisation de Spring Security
Mémo d'utilisation de JCA (Java Encryption Architecture)
En-tête de réponse de mémo d'utilisation de Spring Security
Gestion des sessions de mémo d'utilisation de Spring Security
Mémo d'utilisation de Spring Security Basic / mécanisme
Mémo entier
mémo docker
Spring Security Usage Memo Domain Object Security (ACL)
Mémo de Lombok
Mémo Dockerfile
Mémo Java
Mémo AWS
Mémo Dcokerfile
utilisation d'irb
Memo Stream