Commit 02fe2634 authored by Alex Marandon's avatar Alex Marandon

Ajout de la partie "plateforme"

parent 08df544f
......@@ -277,7 +277,11 @@
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![](img/erlang-ecosystem.png)\n",
"\n",
......@@ -329,7 +333,7 @@
"### Logiciels libres en Elixir\n",
"\n",
"- Réseau social décentralisé : [Pleroma](https://www.pleroma.com/)\n",
"- Plateforme de vérfication d'information : [CaptainFact](https://captainfact.io/)\n",
"- Plateforme de vérification d'information : [CaptainFact](https://captainfact.io/)\n",
"- Site de news sur le dev : [Changelog](https://github.com/thechangelog)\n",
"- Bot GitHub : [Bors](https://bors.tech/)"
]
......@@ -386,9 +390,20 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 19,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": [
"[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"squares = Enum.map(1..10, fn x ->\n",
" x * x\n",
......@@ -397,7 +412,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 20,
"metadata": {},
"outputs": [
{
......@@ -406,7 +421,7 @@
"[4, 16, 36, 64, 100]"
]
},
"execution_count": 2,
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
......@@ -430,7 +445,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 21,
"metadata": {
"slideshow": {
"slide_type": "fragment"
......@@ -443,7 +458,7 @@
"%{author: \"Bob\", date: ~D[2019-11-14]}"
]
},
"execution_count": 3,
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
......@@ -454,7 +469,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 22,
"metadata": {
"slideshow": {
"slide_type": "fragment"
......@@ -496,7 +511,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 23,
"metadata": {
"scrolled": true,
"slideshow": {
......@@ -510,7 +525,7 @@
"%{author: \"Bob\", body: \"C'est quoi Elixir\", date: ~D[2019-11-14]}"
]
},
"execution_count": 5,
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
......@@ -532,7 +547,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 24,
"metadata": {
"slideshow": {
"slide_type": "fragment"
......@@ -545,7 +560,7 @@
"%{author: \"Bob\", date: ~D[2019-11-14]}"
]
},
"execution_count": 6,
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
......@@ -556,7 +571,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 25,
"metadata": {
"slideshow": {
"slide_type": "subslide"
......@@ -569,7 +584,7 @@
"%{author: \"Bob\", body: \"C'est quoi Elixir ?\", date: ~D[2019-11-14]}"
]
},
"execution_count": 7,
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
......@@ -590,7 +605,13 @@
"## immutabilité ⇒ lisibilité\n",
"\n",
"- moins d'ambiguité\n",
"- contexte explicite"
"- contexte explicite\n",
"\n",
"```elixir\n",
"data = copy(something)\n",
"result = do_something_with(data)\n",
"data == something\n",
"```"
]
},
{
......@@ -633,7 +654,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 27,
"metadata": {
"slideshow": {
"slide_type": "subslide"
......@@ -643,22 +664,22 @@
{
"data": {
"text/plain": [
"%{author: \"Bob\", body: \"C'est quoi Elixir ?\", date: ~D[2019-11-14]}"
"\"Bob\""
]
},
"execution_count": 8,
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%{author: author} = message\n",
"message"
"author"
]
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 28,
"metadata": {
"slideshow": {
"slide_type": "fragment"
......@@ -671,7 +692,7 @@
"%{author: \"Bob\", body: \"C'est quoi Elixir ?\", date: ~D[2019-11-14]}"
]
},
"execution_count": 9,
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
......@@ -682,7 +703,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 29,
"metadata": {
"slideshow": {
"slide_type": "fragment"
......@@ -704,7 +725,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 29,
"metadata": {
"slideshow": {
"slide_type": "fragment"
......@@ -726,7 +747,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 29,
"metadata": {
"slideshow": {
"slide_type": "subslide"
......@@ -739,7 +760,7 @@
"\"Message écrit par ce bon vieux Bob: C'est quoi Elixir ?\""
]
},
"execution_count": 10,
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
......@@ -787,20 +808,29 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 30,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[33mwarning: \u001b[0mredefining module Chat (current version defined in memory)\n",
" nofile:1\n",
"\n"
]
},
{
"data": {
"text/plain": [
"\"Ah c'est toi !\""
]
},
"execution_count": 11,
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
......@@ -817,7 +847,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 31,
"metadata": {
"slideshow": {
"slide_type": "fragment"
......@@ -830,7 +860,7 @@
"\"Bonjour José Valim !\""
]
},
"execution_count": 12,
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
......@@ -841,7 +871,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 32,
"metadata": {
"slideshow": {
"slide_type": "fragment"
......@@ -854,7 +884,7 @@
"\"hmm?\""
]
},
"execution_count": 13,
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
......@@ -876,7 +906,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 33,
"metadata": {
"slideshow": {
"slide_type": "subslide"
......@@ -889,7 +919,7 @@
"\"ELF\""
]
},
"execution_count": 14,
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
......@@ -901,7 +931,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 34,
"metadata": {
"scrolled": true,
"slideshow": {
......@@ -915,7 +945,7 @@
"\"Exécutable 64 bits\""
]
},
"execution_count": 15,
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
......@@ -947,7 +977,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 36,
"metadata": {
"slideshow": {
"slide_type": "subslide"
......@@ -969,7 +999,7 @@
"{:module, Chat, <<70, 79, 82, 49, 0, 0, 9, 40, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 46, 0, 0, 0, 33, 11, 69, 108, 105, 120, 105, 114, 46, 67, 104, 97, 116, 8, 95, 95, 105, 110, 102, 111, 95, 95, 7, 99, ...>>, {:display, 1}}"
]
},
"execution_count": 16,
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
......@@ -993,7 +1023,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 37,
"metadata": {
"slideshow": {
"slide_type": "subslide"
......@@ -1004,8 +1034,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[11:12:14.698426] Bob: C'est quoi Elixir ?\n",
"[11:12:14.698504] Alice: C'est un langage de programmation.\n"
"[14:00:07.034512] Bob: C'est quoi Elixir ?\n",
"[14:00:07.034549] Alice: C'est un langage de programmation.\n"
]
},
{
......@@ -1014,7 +1044,7 @@
"[:ok, :ok]"
]
},
"execution_count": 17,
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
......@@ -1028,7 +1058,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 38,
"metadata": {
"slideshow": {
"slide_type": "subslide"
......@@ -1039,8 +1069,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[11:12:14.877576] Bob: C'est quoi Elixir ?\n",
"[11:12:14.877630] Alice: C'est un langage de programmation.\n"
"[14:00:54.906802] Bob: C'est quoi Elixir ?\n",
"[14:00:54.906858] Alice: C'est un langage de programmation.\n"
]
},
{
......@@ -1049,7 +1079,7 @@
"[:ok, :ok]"
]
},
"execution_count": 18,
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
......@@ -1076,6 +1106,395 @@
"- les sigils eg. `~w(liste de mots)`\n",
"- vérification de types optionnelle"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## La plateforme Erlang/OTP\n",
"\n",
"- processus légers\n",
"- communication par passage de messages\n",
"- serveurs génériques\n",
"- tolérance aux erreurs\n",
"- supervision\n",
"- application"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Processus légers\n",
"\n",
"#### spawn"
]
},
{
"cell_type": "code",
"execution_count": 97,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"#PID<0.19162.1>"
]
},
"execution_count": 97,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pid = spawn(\n",
" fn -> Process.sleep(30_000)\n",
"end)\n",
"pid"
]
},
{
"cell_type": "code",
"execution_count": 98,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"true"
]
},
"execution_count": 98,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Process.alive?(pid)"
]
},
{
"cell_type": "code",
"execution_count": 99,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"false"
]
},
"execution_count": 99,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Process.exit(pid, :kill)\n",
"Process.alive?(pid)"
]
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"text/plain": [
"164"
]
},
"execution_count": 100,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":erlang.system_info(:process_count)"
]
},
{
"cell_type": "code",
"execution_count": 109,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"50000"
]
},
"execution_count": 109,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"1..50_000\n",
"|> Enum.map(fn _ ->\n",
" spawn(fn -> Process.sleep(10_000) end)\n",
"end)\n",
"|> length"
]
},
{
"cell_type": "code",
"execution_count": 113,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"150"
]
},
"execution_count": 113,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":erlang.system_info(:process_count)"
]
},
{
"cell_type": "code",
"execution_count": 114,
"metadata": {
"scrolled": true,
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"text/plain": [
"262144"
]
},
"execution_count": 114,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":erlang.system_info(:process_limit)"
]
},
{
"cell_type": "code",
"execution_count": 115,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 115,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":erlang.system_info(:schedulers)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Communication par passage de messages\n",
"\n",
"send/receive"
]
},
{
"cell_type": "code",
"execution_count": 122,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"#PID<0.233.0>\n",
"#PID<0.10406.5>\n"
]
},
{
"data": {
"text/plain": [
"\"Le process m'a envoyé : j'ai fini\""
]
},
"execution_count": 122,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"parent_process = self() |> IO.inspect\n",
"\n",
"spawn(fn ->\n",
" IO.inspect(self())\n",
" Process.sleep(2000)\n",
" send(parent_process, {:response, \"j'ai fini\"})\n",
"end)\n",
"\n",
"receive do\n",
" {:response, message} -> \"Le process m'a envoyé : #{message}\"\n",
"after\n",
" 5000 -> :timeout\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Serveur générique\n",
"\n",
"### `GenServer`\n",
"\n",
"Boucle infinie :\n",
"\n",
"1. démarre avec un *état* (state) donné\n",
"2. attend un message\n",
"3. appelle callback fournie nous pour traiter le message\n",
"4. notre callback peut transformer l'état et renvoyer une réponse\n",
"5. retour à l'étape 2"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Tolérance aux erreurs\n",
"\n",
"- processus isolés\n",
"- par défaut une erreur dans un processus n'affecte pas les autres"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Supervision\n",
"\n",
"### `Supervisor`\n",
"\n",
"- lance des processus\n",
"- observe ces processus\n",
"- relance les processus en cas de crash\n",
"\n",
"> \"Let it crash\""
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Application\n",
"\n",
"- définit un composant réutilisable (un *package*)\n",
"- peut être ajouté en dépendance d'un autre projet\n",
"- contient du code mais aussi **un modèle d'exécution**"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Poursuivre la découverte\n",
"\n",
"- Excellente présentation en anglais : [The Soul of Erlang and Elixir](https://www.youtube.com/watch?v=JvBT4XBdoUE)\n",
"- Guide officiel en anglais : [Getting Started](https://elixir-lang.org/getting-started/introduction.html)\n",
"- Très bon tutoriel en français : [Découverte du langage Elixir](https://www.youtube.com/watch?v=1hl_z9-QO9c)\n",
"- Tutoriel en français sur [Elixir School](https://elixirschool.com/fr/lessons/basics/basics/)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Cette présentation\n",
"\n",
"Support : https://gitlab.com/amarandon/presentation-elixir\n",
"\n",
"Projet d'exemple : https://gitlab.com/amarandon/chat-example"
]
}
],
"metadata": {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment