Files
olla/content/talks/orleans-tech-programmation-fonctionnelle/index.html
2026-02-18 17:23:24 +01:00

353 lines
16 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Programmation fonctionnelle pour les développeuses·eurs web</title>
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/theme/solarized.css">
<!-- Theme used for syntax highlighting of code -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<style media="screen">
.fragment.current-visible.visible:not(.current-fragment) {
display: none;
height:0px;
line-height: 0px;
font-size: 0px;
}
</style>
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h3>La programmation fonctionnelle</h3>
<h4> pour les développeuses·eurs web</h4>
<small><a href="https://twitter.com/ThibaudDauce">@ThibaudDauce</a> | <a href="https://thibaud.dauce.fr">https://thibaud.dauce.fr</a></small>
</section>
<section>
<img src="images/quantic-telecom.png" alt="Quantic Telecom" />
<h4>Co-fondateur de Quantic Telecom</h4>
<small><a href="https://www.quantic-telecom.net">https://www.quantic-telecom.net</a></small>
<hr>
<img src="images/laravel.png" alt="Formations Laravel" />
<h4>Formations Laravel</h4>
<small><a href="https://www.formations-laravel.fr">https://www.formations-laravel.fr</a></small>
</section>
<section>
<h3>La programmation fonctionnelle</h3>
<h4> pour les développeuses·eurs web</h4>
<small><a href="https://twitter.com/ThibaudDauce">@ThibaudDauce</a> | <a href="https://thibaud.dauce.fr">https://thibaud.dauce.fr</a></small>
</section>
<section>
<h3>Euh… J'en fais déjà, non ?</h3>
<pre class="fragment"><code data-trim data-noescape class="php">
// Get invoices
$api = new API()
$result = $api->post('/invoices', []);
$invoices = json_decode($result);
// Get students
$customers = Customer::all();
$students = [];
foreach ($customers as $customer) {
if ($customer->isStudent()) {
$students[] = $customer;
}
}
</pre></code>
</section>
<section>
<h3>Euh… J'en fais déjà, non ?</h3>
<pre><code data-trim data-noescape class="php">
// Get invoices
$invoices = getInvoices();
// Get students
$students = getStudents();
</pre></code>
</section>
<section>
<h3>Votre serveur web est une fonction</h3>
<h4><span class="fragment">Requête HTTP</span> <span class="fragment">&#8594; Réponse HTTP</span></h4>
</section>
<section>
<pre><code data-trim data-noescape class="php">
// 1. Vérifiez que la personne est connectée
// 2. Enregistrer le début du traitement de la requête
// 3. Faire ce que tu as à faire
// (retourne une chaîne de caractères)
// 4. Transformer la chaîne de caractères en réponse HTTP
// 5. Enregistrer le temps de traitement grâce à 2.
<span class="fragment">
$tasks = [
new CheckAuthentication,
new LogRequestTime,
new TransformToResponse,
];</span>
</pre></code>
</section>
<section>
<h3>Pipelines / Middlewares</h3>
<pre><code data-trim data-noescape class="php">
(new Pipeline)
->send(Request::createFromGlobals())
->through([
new CheckAuthentication,
new LogRequestTime,
new TransformToResponse,
])
->then(function ($request) {
return "Welcome {$request->session('customer')}!";
});
</span>
</pre></code>
</section>
<section>
<pre><code data-trim data-noescape class="php">
class CheckAuthentication
{
public function handle($request, $next)
{
if (! $request->session()->has('customer')) {
return new RedirecResponse('/login', 302);
}
return $next($request);
}
}
</pre></code>
</section>
<section>
<pre><code data-trim data-noescape class="php">
class LogRequestTime
{
public function handle($request, $next)
{
$start = microtime(true);
$response = $next($request);
$time = microtime(true) - $start;
$text = "Request {$request->requestUri} took {$time}s \n";
file_put_content('timings.txt', $text, FILE_APPEND);
return $response;
}
}
</pre></code>
</section>
<section>
<pre><code data-trim data-noescape class="php">
class TransformToResponse
{
public function handle($request, $next)
{
$response = $next($request);
if ($response instanceof Response) {
return $response;
}
return new Response((string) $response, 200);
}
}
</pre></code>
</section>
<section>
<pre><code data-trim data-noescape class="php">
function ($request) {
return "Welcome {$request->session('customer')}!";
}
</pre></code>
</section>
<section>
<h3>Votre serveur web est une fonction</h3>
<h4>(Le retour)</h4>
<ol>
<li class="fragment">Requête HTTP &#8594; Identifiant client</li>
<li class="fragment">Identifiant client &#8594; Client</li>
<li class="fragment">Client &#8594; Total des comptes</li>
<li class="fragment">Total des comptes &#8594; Page HTML</li>
<li class="fragment">Page HTML &#8594; Réponse</li>
</ol>
</section>
<section>
<h3>Collections</h3>
<pre><code data-trim data-noescape class="php">
function getMonthlyMeanRevenueForStudents() {
$customers = Customer::all();
$totalRevenue = [];
$counts = [];
foreach($customers as $customer) {
if ($customer->isStudent()) {
foreach($customer->invoices() as $invoice) {
$totalRevenue[$invoice->month()] +=
$invoice->total();
$counts[$invoice->month()]++;
}
}
}
$meanRevenue = [];
foreach ($revenues as $month => $total) {
$meanRevenue[$month] = $totalRevenue[$month] / $counts[$month];
}
return $meanRevenue;
}
</pre></code>
</section>
<section>
<h3>Collections</h3>
<pre><code data-trim data-noescape class="php">
function getMonthlyMeanRevenueForStudents() {
<span class="fragment" data-fragment-index="0">return Customer::all()</span><span class="fragment current-visible" data-fragment-index="0">
// [
// 'Étudiant John',
// 'Étudiante Jane',
// 'Entreprise Google',
// ]</span>
<span class="fragment" data-fragment-index="1">->filter(function ($customer) {
return $customer->isStudent();
})</span><span class="fragment current-visible" data-fragment-index="1">
// [
// 'Étudiant John',
// 'Étudiante Jane',
// ]</span>
<span class="fragment" data-fragment-index="2">->map(function ($customer) {
return $customer->invoices();
})<span class="fragment current-visible" data-fragment-index="2">
// [
// ['2017-07-001', '2017-08-001'],
// ['2017-07-002'],
// ]</span>
<span class="fragment" data-fragment-index="3">->flatten()<span class="fragment current-visible" data-fragment-index="3">
// [ '2017-07-001', '2017-08-001', '2017-07-002' ]</span>
<span class="fragment" data-fragment-index="4">->groupBy(function ($invoice) {
return $invoice->month();
})<span class="fragment current-visible" data-fragment-index="4">
// [
// '2017-07' => ['2017-07-001', '2017-07-002'],
// '2017-08' => ['2017-08-001'],
// ]</span>
<span class="fragment" data-fragment-index="5">->map(function ($invoices) {</span>
<span class="fragment current-visible" data-fragment-index="5">// = ['2017-07-001', '2017-07-002']</span><span class="fragment current-visible" data-fragment-index="6">// = [80, 100]</span><span class="fragment current-visible" data-fragment-index="7">// = 180</span><span class="fragment current-visible" data-fragment-index="8">// = 90</span>
<span class="fragment" data-fragment-index="6">return $invoices->map(function ($invoice) {
return $invoice->total();
})</span><span class="fragment" data-fragment-index="7">->sum()</span><span class="fragment" data-fragment-index="8"> / $invoices->count();</span>
<span class="fragment" data-fragment-index="5">});</span>
<span class="fragment current-visible" data-fragment-index="9">
// [
// '2017-07' => 90,
// '2017-08' => 150,
// ]</span>
}
</pre></code>
</section>
<section>
<h3>Collections</h3>
<pre><code data-trim data-noescape class="php">
function getMonthlyMeanRevenueForStudents() {
return Customer::all()
->filter->isStudent()
->flatMap->invoices()
->groupBy->month()
->map(function ($invoices) {
return $invoices->map->total()->sum() / $invoices->count();
});
}
</pre></code>
</section>
<section>
<h3>Un peu de Front-End</h3>
<h4 class="fragment">Elm</h4>
</section>
<section>
<h3>MVU</h3>
<h4 class="fragment"><strong>M</strong>odel <strong>V</strong>iew <strong>U</strong>pdate</h4>
</section>
<section>
<h3>Model</h3>
<pre><code data-trim data-noescape class="elm">
type alias Model = String
</pre></code>
<pre class="fragment"><code data-trim data-noescape class="elm">
init : Model
init = ""
</pre></code>
</section>
<section>
<h3>Update</h3>
<pre><code data-trim data-noescape class="elm">
type Event = Typed String
</pre></code>
<pre class="fragment"><code data-trim data-noescape class="elm">
update : Event -> Model -> Model
update (Typed textTyped) oldTextTyped = textTyped
</pre></code>
</section>
<section>
<h3>View</h3>
<pre><code data-trim data-noescape class="elm">
view : Model -> Html Event
view textTyped =
div []
[ input [ placeholder "Text to reverse", onInput Typed ] []
, div [] [ text (String.reverse textTyped) ]
]
</pre></code>
</section>
<section>
<h3><a href="http://elm-lang.org">elm-lang.org</a></h3>
</section>
<section>
<h3>D'autres ressources</h3>
<ul>
<li><a href="https://medium.com/@jeffochoa/understanding-laravel-pipelines-a7191f75c351">Understanding Laravel Pipelines</a></li>
<li><a href="https://adamwathan.me/refactoring-to-collections/">Refactoring to Collection</a></li>
<li><a href="http://haskellbook.com/">Haskell Book</a></li>
<li><a href="http://www.purescript.org/">PureScript</a></li>
<li><a href="https://leanpub.com/purescript/">Learn PureScript by Example</a></li>
</ul>
</section>
<section>
<h3>Merci à tous</h3>
<small><a href="https://twitter.com/ThibaudDauce">@ThibaudDauce</a> | <a href="https://thibaud.dauce.fr">https://thibaud.dauce.fr</a></small>
</section>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.js"></script>
<script>
// More info about config & dependencies:
// - https://github.com/hakimel/reveal.js#configuration
// - https://github.com/hakimel/reveal.js#dependencies
Reveal.initialize({
dependencies: [
{ src: 'plugin/markdown/marked.js' },
{ src: 'plugin/markdown/markdown.js' },
{ src: 'plugin/notes/notes.js', async: true },
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }
]
});
</script>
</body>
</html>