### La programmation fonctionnelle

#### pour les développeuses·eurs web

@ThibaudDauce | https://thibaud.dauce.fr

#### Co-fondateur de Quantic Telecom

https://www.quantic-telecom.net

#### Thibaud Dauce sur YouTube

https://www.apprendre-laravel.fr

### La programmation fonctionnelle

#### pour les développeuses·eurs web

@ThibaudDauce | https://thibaud.dauce.fr

### Il y a 3 ans…

### Haskell c'est quoi ?

- pas de conditions
- pas de boucles
- pas de variables

                            function getStudents() {
                                $customers = Customer::all();
                                $students = [];

                                foreach($customers as $customer) {
                                    if ($customer->isStudent()) {
                                        $students[] = $customer;
                                    }
                                }

                                return $students;
                            }

                            function getStudents() {
                                $customers = Customer::all();

                                return array_filter($customers, function ($customer) {
                                    return $customer->isStudent();
                                });
                            }

                            function getStudents() {
                                return Customer::all()
                                    ->filter(function ($customer) {
                                        return $customer->isStudent();
                                    });
                            }

                            function getStudents() {
                                $customers = Customer::all();

                                return array_filter(array_filter($customers, function ($customer) {
                                    return $customer->isStudent();
                                }), function ($student) {
                                    return $student->isValid();
                                });
                            }

                            function getStudents() {
                                return Customer::all()
                                    ->filter(function ($customer) {
                                        return $customer->isStudent();
                                    });
                                    ->filter(function ($student) {
                                        return $customer->isValid();
                                    });
                            }

                            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 ($totalRevenue as $month => $total) {
                                    $meanRevenue[$month] = $total / $counts[$month];
                                }

                                return $meanRevenue;
                            }

                        function getMonthlyMeanRevenueForStudents() {
                            return Customer::all()
                                // [
                                //     'Étudiant John',
                                //     'Étudiante Jane',
                                //     'Entreprise Google',
                                // ]
                                ->filter(function ($customer) {
                                    return $customer->isStudent();
                                })
                                // [
                                //     'Étudiant John',
                                //     'Étudiante Jane',
                                // ]
                                ->map(function ($student) {
                                    return $student->invoices();
                                })
                                // [
                                //     ['2019-03-001', '2019-04-001'],
                                //     ['2019-03-002'],
                                // ]
                                ->flatten()
                                // [ '2019-03-001', '2019-04-001', '2019-03-002']
                                ->groupBy(function ($invoice) {
                                    return $invoice->month();
                                })
                                // [
                                //     '2019-03' => ['2019-03-001', '2019-03-002'],
                                //     '2019-04' => ['2019-04-001'],
                                // ]
                                ->map(function ($invoices) {
                                    // = ['2019-03-001', '2019-03-002']// = [80, 100]// = 180// = 90
                                    return $invoices->map(function ($invoice) {
                                        return $invoice->total();
                                    })->sum() / $invoices->count();
                                });
                                // [
                                //     '2019-03' => 90,
                                //     '2019-04' => 150,
                                // ]
                        }

                            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 ($totalRevenue as $month => $total) {
                                    $meanRevenue[$month] = $total / $counts[$month];
                                }

                                return $meanRevenue;
                            }

### PHP RFC: Arrow Functions 2.0

                        function getMonthlyMeanRevenueForStudents() {
                            return Customer::all()
                                ->filter(fn($customer) => $customer->isStudent())
                                ->flatMap(fn($student) => $student->invoice())
                                ->groupBy(fn($invoice) => $invoice->month())
                                ->map(function ($invoices) {
                                    $total = $invoices
                                        ->map(fn($invoice) => $invoice->total())
                                        ->sum();
                                    return $total / $invoices->count();
                                });
                        }

### Middlewares

#### Gestion d'une Chaîne de traitement

### Requête HTTP → Réponse HTTP

### 3 problèmes

- Vérifiez que la personne est connectée
- Ajouter un header HTTP à toutes les réponses
  (`Content-Language: fr`)
- Enregistrer le temps de traitement d'une requête

                            function myMiddleware(Request $request, $next): Response
                            {
                                // $next = function (Request $request): Response {
                                //      return new Response(200, 'All good!');
                                // };

                                $response = $next($request);
                                return $response;
                            }

### Vérifiez que la personne est connectée

                            function authMiddleware(Request $request, $next): Response
                            {
                                if (! $request->session()->has('user')) {
                                    return new Response(302, '/login');
                                }

                                $response = $next($request);
                                return $response;
                            }

### Ajouter un header HTTP à chaque réponse

                            function contentLanguageMiddleware(Request $request, $next): Response
                            {
                                $response = $next($request);

                                $response->headers()->add('Content-Language', 'fr');

                                return $response;
                            }

### Enregistrer le temps de traitement d'une requête

                            function timeMiddleware(Request $request, $next): Response
                            {
                                $start = microtime(true);

                                $response = $next($request);

                                $time = microtime(true) - $start;
                                $text = "Request {$request->url()} took {$time}s \n";
                                file_put_content('timings.txt', $text, FILE_APPEND);

                                return $response;
                            }

### Exemples de middlewares avec Laravel

                            $middlewares = [
                                CheckForMaintenanceMode::class,
                                EncryptCookies::class,
                                StartSession::class,
                                ThrottleRequests::class,
                                ConvertEmptyStringsToNull::class,
                            ];

### L'ordre des middlewares

                            $middlewares = [
                                'authMiddleware',
                                'contentLanguageMiddleware',
                                'timeMiddleware',
                            ];

                            $middlewares = [
                                'timeMiddleware',
                                'authMiddleware',
                                'contentLanguageMiddleware',
                            ];

                            function otherMiddleware(ClasseA $classeA, $next): ClasseB
                            {
                                // $next = function (ClasseA $classeA): ClasseB {
                                //      return new ClasseB;
                                // };

                                $classeB = $next($classeA);
                                return $classeB;
                            }

### Un peu de Front-End

#### Elm

### MVU

#### Model View Update

### Model

                            type alias Model = String

                            init : Model
                            init = "Thibaud"

### Update

                            type Event = NewName String | Reverse

                            update : Event -> Model -> Model
                            update event oldName = case event of
                                NewName newName -> newName
                                Reverse -> String.reverse oldName

### View

                            view : Model -> Html Event
                            view name =
                                div []
                                    [ input [ placeholder "New Name", onInput NewName, value name ] []
                                    , button [ onClick Reverse ] [ text "Reverse Name" ]
                                    , div [] [ text name ]
                                    ]

### elm-lang.org

### D'autres ressources

- Refactoring to Collection
- Haskell Book
- PureScript
- Ma chaîne YouTube « Thibaud Dauce »

### Merci à tous

@ThibaudDauce | https://thibaud.dauce.fr