Collaboration à la conception d’applications¶

Introduction¶

Présentation du Cours¶

Objectif du cours¶

  1. Les éléments de la POO dans le contexte du Web

  2. La création de conteneurs d’objets

  3. Disposition du contenu de ces objets dans la page du client.

En gros¶

  1. On veut continuer à apprendre javascript

  2. Introduction à la conception d’applications : parce qu'il faut

  3. Méthode Agile: Pour être trendy

  4. Conception générale et détaillée: Parce que nous aimons le code.

Lien principal¶

https://all-dressed-programming.com/courses/420-301-ah/

Présentation de l'Enseignant¶

didier amyot¶

  • Étudié en mathématiques

  • Programmeur avant toutes choses

    • Python

    • Java

    • Clojure

    • Go

    • Rust

    • JavaScript/TypeScript

  • Travaillé à trop de places.

  • $5^{ime}$ cours que j'enseigne

didier amyot¶

  • J'ai deux chiens (Molly & Pepper)

  • J'habite avec un chat

Présentation des Étudiants¶

Étudiants¶

  • Votre nom

  • Vous étudiez en quoi

  • Vous aimez quoi

  • Language de programmation préféré

Présentation des Objectifs Du Cours¶

Détails¶

  • Pondération 1-2-2

  • Comment me contacter (didier.amyot@collegeahuntsic.qc.ca)

  • Horaires - mercredi & vendredi de 13h00 à 16h00

  • Cours du mercredi sur place

  • Cours du vendredi, sur "meet"

  • Présence en classe

  • Évaluations

  • Plagiat (ChatGPT)

Item à discuter¶

  • Nous avons un gros congé pour le temps des fêtes

  • Grêve des enseignants

  • Reprise de cours?

  • Horaire des évaluations

Programmation Client II¶

Rappel¶

Types et opérateurs de bases¶

Déclarer, initialiser des valeurs¶

// For values that change
let name = "didier";
name = "paulette";


// For values that never change
const age = 37;

Les types de bases¶

nom exemple description
boolean true/false Représente un valeur vraie ou fausse
number 12, 0, -19, 3.14159 Représente un nombre quelconque
String "Bonjour", 'les amis' Représente du texte
undefined undefined Représente un inconnue provenant de javascript
null null Représente un inconnue provenant du programmeur

Égalité entre valeurs¶

Pour que deux variables soient === il faut que les deux variables aillent le même type et la même valeur.

let message1 = "Bonjour le monde"

let message2 = "привет мир";
let message1EqualsMessage2 = (message1 === message2); // false

Les opérations sur les booléen¶

Définition Opérateur Exemple
Égalité entre deux boolean === true === true
et logique && true && true
ou logique || true || false
Négatif ! !false

Opérations sur les nombres¶

Définition Opérateur Exemple
Égalité entre deux nombres === 10 === 10
Somme + 2 + 2 === 4
Produit * 3 * 4 === 12
Division / 12 / 3 === 12
Modulo % 7 % 3 === 1

Les comparaison de nombres¶

Définition Opérateur Exemple
Égalité entre deux nombres === 2 + 2 === 4
Strictement plus petit < 2 < 4
Plus petit (ou égale) <= 4 <= 4
Strictement plus grand > 4 > 2
Plus grand (ou égale) >= 4 >= 4

Opérations sur les strings¶

Définition Opérateur Exemple
Égalité entre deux strings === "Japon" === "Japon"
concaténation + "Bonjour " + "le monde" === "Bonjour le monde"

Méthodes courantes sur les strings¶

Définition Méthode Exemple Notes
Nombre de lettres dans la string .length "Japon".length === 5 plein de bug pour les gens qui écrivent dans des langues bizzards*
Mettre en lettre majuscule .toUpperCase() "Japon".toUpperCase() === "JAPON"
Mettre en lettre minuscule .toLowerCase() "Japon".toLowerCase() === "japon"
Lettre à une position précise .charAt() "Japon".charAt(3) === "o" plein de bug pour les gens qui écrivent dans des langues bizzards*

langues bizzards: surtout les emoji. Même le chinois langues bizzards m'a l'air de fonctionnner

Conditions¶

Le ifs¶

if(age > 18){
    alert("the user is major");
} else {
    alert("the user is minor");
}

Condition multiple¶

if(age > 21){
    alert("the user is major in the US.");
} else if (age > 18) {
    alert("the user is major in real countries but not in the empire.");
}else {
    alert("the user is minor.");
}

Condition sans else¶

if(age > 18){
    alert("the user is major");
}
  • On beaucoup aime les if sans else

  • On aime les if avec else

  • On tollère les if avec des else if

La syntaxe¶

if(la condition){
    // quoi faire si la condition est vraie
} else {
    // quoi faire si la condition est fausse
}

La condition¶

  • Devrait être un boolean mais pas nécessairement...

Toutes valeurs sauf les valeurs si bas sont considérées comme vraies.

  • null, la valeur null
  • undefined, la valeur undefined
  • false, la faux
  • NaN, not a number (exemple parseInt("sdjkds"))
  • 0, zero
  • "", le string vide

https://developer.mozilla.org/en-US/docs/Glossary/Falsy

Exemples 1¶

let name = "";
if(!name){
    name = "no name";
}
console.log(name);

Exemples 2¶

let name;
if(!name){
    name = "no name";
}
console.log(name);

Exemples 2¶

let name = null;
if(!name){
    name = "no name";
}
console.log(name);

Exemples 3¶

let person = {};
if(!person.name){
    person.name = "";
}
console.log(person);

Exemples 4¶

let persons = [];
if(!persons.length){
    persons.push({name: "didier"});
}
console.log(persons);

functions¶

Définition fonction¶

D'un point de vue impératif¶

Une fonction est un bout de code nommé que nous pouvons appelé. Les vieux de la vieille apelle cela une "(sub)routine"

// un bout de code nommé sayHello qui dit "Hello World!"
function sayHello(){
    alert("hello world");
}

Définition mathématique¶

D'un point de vue impératif¶

En mathématiques, une fonction est un type de relation $f$ entre deux variables. On appelle cette relation une fonction lorsque chaque valeur de la variable indépendante est associée à une et une seule valeur de la variable dépendante.

-- https://www.alloprof.qc.ca/fr/eleves/bv/mathematiques/relations-et-fonctions-m1095

syntaxe fonctions¶

function sayHello(){
    alert("hello world");
}

function addNumber(a, b){
    return a + b;
}

function isMajorMessage(age){
    if(age < 18){
        return "user is minor";
    }
    if(age < 21){
        return "user is minor in crazy countries";
    }
    return "user is major"
}

Syntaxe¶

Notes sur les fonctions¶

Les arguments d'une fonction sont connue de la fonction seulement.

Les deux fonctions ci-bas sont les mêmes

function add(a, b){
    return a + b;
}
function add(x, y){
    return x + y;
}

Nom d'une fonction¶

  • Le nom d'une fonction doit être unique

  • Le nom de la fonction devrait être un verbe

  • Moins que la fonction est utilisé de fois, plus son nom devrait être long

function add2AndMultiplyBy3(a){
    return (a + 2) * 3;
}

Retourner une valeur d'une fonction¶

  • Une fonction peut retourner au maximum une seule valeure

  • À l'instant que la fonction retourne, l'execution de la fonction se termine

function getMinorityStatus(age){
    if(age < 18){
        return "minor";
    }
    if(age < 21){
        return "minor in the empire";
    }
    return "major";

}

console.log(getMinorityStatus(12)); // "minor"
console.log(getMinorityStatus(19)); // "minor in the empire"
console.log(getMinorityStatus(87)); // "major"

Appeler une fonction¶

On utilise la notation nomDeLaFonction(argument1, argument2)

function add(a, b){
    return a + b;
}

function multiply(a, b){
    return a * b;
}

console.log(add(2, 3));
console.log(add(2, multiply(4, 5)));
let x = multiply(2, 3);
console.log(add(2, x));
console.log(
    add(8, 
        multiply(10, 6))
);

Listes et boucles¶

Boucle for classique¶

for(let i = 0; i < 10; i ++){
    console.log(i);
}
  1. inititalilation : let i = 0
  2. condition : i < 10
  3. incrémentation: i = i + 1

Créer une liste.¶

let emptyList = [];

let beerList = ["bud weiser", "ipa du nord-est", "headdy topper"];

let grades = [90, 65, 40, 55];

Opération sur les listes¶

let beerList = ["bud weiser", "ipa du nord-est", "headdy topper"];

//  longeur d'une liste
console.log(beerList.length);

// ajouter un élément à une liste
beerList.push("peche mortel");

// element d'une liste
// l'indice commence par 0!!!!!!!!!
alert(beerList[2]); // "headdy topper"

Boucle for each¶

(on aime beaucoup les boucles for each)

for(const beer of beerList){
    console.log(beer);
}

Objets¶

Object javascript¶

  • Un objet javascript est une collection clé/valeur

  • Les clés sont des strings

  • En d'autres languages

    • Dictionnaire
    • Map
    • HashMap

Rien de mieux qu'un exemple¶

let beer = {
    nom: "Péché Mortel",
    brasserie: "Dieu du Ciel!",
    quantity: 350,
    prix: 5.99,
}

L'object vide!¶

{}

Méthodes sur objet¶

let beer = {
    nom: "Péché Mortel",
    brasserie: "Dieu du Ciel!",
    quantity: 350,
    prix: 5.99,
}

// Prendre une valeur par une variable
console.log(beer.name)

// associer une nouvelle valeur
beer.nom = "grande noirceur";

// Prendre toutes les clés
Object.keys(beer);

Looper sur tous les items d'un objet¶

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

let beer = {
    nom: "Péché Mortel",
    brasserie: "Dieu du Ciel!",
    quantity: 350,
    prix: 5.99,
}

for(let key of Object.keys(beer)){
    let value = beer[key];
    console.log(key + " : " + value);
}

Exercice Récapitulatif¶

Faisons la question 6.o. de https://didier-ahuntsic.gitlab.io/cours-420-298-ah/_exercices/007.pdf

Pour ce faire, nous allons procéder ainsi:

  1. faire un plan

  2. suivre le plan

Programmation Client II¶

Strings template¶

Strings template¶

Comment nous créons des strings¶

Double quotes¶

let message = "Ceci est un petit texte";

Simple quotes¶

let message = 'Ceci est un autre petit texte';

Mais, nous pouvons demander de mieux¶

  1. Un string qui contient un text avec plusieurs lignes

  2. Un string qui permet de remplacer façilement une variable

Les templates literals font tout ça!¶

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

let message = `Ceci est un texte normal`;

Un string qui contient un text avec plusieurs lignes¶

let multiLineMessage = `un
deux
trois`;
console.log(multiLineMessage)
In [20]:
let multiLineMessage = `un
deux
trois`;
console.log("->" + multiLineMessage + "<-");
Out[20]:
->un
deux
trois<-

Un string qui permet de remplacer façilement une variable¶

let name = "Colette"
let message = `Bonjour ${name}`;
console.log(message)
In [21]:
let name = "Colette"
let message = `Bonjour ${name}`;
console.log(message)
Out[21]:
Bonjour Colette
In [22]:
let name = "Colette"
let anneeCourrante = 2023;
let anneeDeNaissance = 1947;
let message = `Bonjour ${name}, vous avez ${anneeCourrante - anneeDeNaissance} années`;
console.log(message)
Out[22]:
Bonjour Colette, vous avez 76 années
In [23]:
let message = `Ceci est totallement \${foo}`;
console.log(message)
Out[23]:
Ceci est totallement ${foo}

Strings exercices¶

  1. Écrire un string qui représente
                #
               ###
              #####
             #######
            ######### 

Écrire un string

Bonjour, mon nom est André André et j'habite Laval.  J'ai 3 chars.

Pour

{
  firstName: "André",
  lastName: "André",
  city: "Laval",
  cars: ["civic", "mustang", "F150"],
}

Programmation Client II¶

js Modules¶

C'est quoi le problème?¶

Les "vraies" affaires¶

  1. Les programmes consistent habituellement en plusieurs fichiers

  2. Les programmes utilisent habituellement des dépendances externes (react, mithril, angular, lodash)

  3. Votre programme sera probablement importer par d'autre programmes

Objectif: Les beauté de l'informatique¶

  1. Il est façile de copier quelque chose

  2. Il est façile de réutiliser quelque chose

Exemple¶

On veut calculer la moyenne d'un groupe d'étudiant. Nous travaillons dans un fichier students.js et nous avons un fichier stats.js avec des fonctions statistiques fait par une statisticienne.

Exemple | fichier stats.js¶

// stats.js
function average(lst){
    if(lst.length < 1){
        return NaN;
    }
    let sum = 0;
    let n = 0;
    for(const e of lst){
        sum += e;
        n += 1;
    }
    return sum / n;
}

Exemple | fichier students.js¶

// students.js

function getFinalGrades(students){
    const grades = [];
    for(const student of students){
        if(student.finalGrade){
            grades.push(finalGrade);
        }
    }
    return grades;
}

function studentAverage(students){
    const finalGrades = getFinalGrades(students);
    const ret = average(finalGrades);
    if(isNaN(ret)){
       return "Aucune note entrées";
    }
    return ret + "%"; 
}

Objectif | minimal¶

  1. Être capable de "merger" les deux fichiers dans le bon ordre

Objectif | hipster¶

  1. Être capable de "merger" les deux fichiers dans le bon ordre

    1. Juste prendre les fonctions que nous vonlons dans un ficher
    2. Être capable de ne pas "exporter" des fonctions
  2. Être capable d'importer des fonction de n'importe où

Terminologie¶

module¶

  1. C'est un fichier javascript

  2. Le fichier utilise une extension .js ou .jsm (javascript module)

  3. C'est une fichier qui peut importer d'autres modules

  4. C'est une fichier qui peut exporter des choses

  5. C'est un fichier qui est dans son propre "scope"/"namespace"

Importer¶

Si un module students.js utilise la fonction average du module stats.js on dira que le module students.js importe la fonction average du module stats.js.

Exporter¶

Si la fonction average du module stats.js peut être importer par un aute module, on dira que la fonction average est exporté par stats.js.

Notion de consentement¶

  1. Un module stats.js doit être consentant pour exporter une fonction average.

  2. Le module students.js n'a pas besoin de l'accord stats.js pour importer la fonction average

Utilisation d'un module dans un site web¶

Dans un fichier .js de la page web¶

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>title</title>
    <script type="module" src="script.js"></script>
</head>
<body>


</body>
</html>
  • La partie importante ici est vraiment le

Les events dans le html ne fonctionneront plus :(¶

Probleme¶

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>title</title>
    <script type="module" src="script.js"></script>
</head>
<body>

  <button onclick=sayHello() id="hello-button">Say Hello</button>
</body>
</html>
  • Meme si script.js contient la fonction sayHello(), cliquer le bouton ne fera rien :(

Solution¶

  • Ajouter l'event en javascript
function sayHello(){
    alert("Bonjour monde!");
}

document.getElementById("hello-button").addEventListener('click', sayHello);

Solution (html)¶

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <script type="module" src="script.js"></script>
</head>
<body>

  <button id="hello-button">Say Hello</button>
</body>
</html>

Avantage¶

  1. Un element peu avoir plusieurs "Event listener"
  2. On aime faire les choses en javascript

Exercices:¶

  • Faire une page web qui utilise un js module avec un boutton et qui aler "hello world" lorsqu'on clique sur le boutton

Importer des fonctions d'un module¶

Importer d'un module dans un fichier à côté¶

import {average} from "./stats.js";

Importer d'un module dans le plus loin¶

import {average} from "https://cdn.jsdelivr.net/gh/didiercrunch/cours-420-301-ah@main/modules-examples/stats.js";
In [15]:
import {average} from "https://cdn.jsdelivr.net/gh/didiercrunch/cours-420-301-ah@main/modules-examples/stats.js";

console.log(average([1,2,3,4]))
Out[15]:
2.5

La syntaxe¶

import {average} from "./stats.js";
  ^       ^       ^      ^ 
  1       2       3      4
  • 1 Le mot import est réservé
  • 2 définit ce que nous importons, c'est le nerf la guerre
  • 3 Le mot from est réservé
  • 4 L'url du module d'où on importe les chose

Importer une fonction¶

import {average} from "./stats.js";


console.log(average([10, 20, 30]));
  • Nous importons la fonction average
  • Dans ce fichier, nous aurons la fonction average définit dans ./stats.js

Importer deux fonctions¶

import {average, std} from "./stats.js";

console.log(average([10, 20, 30]));
console.log(std([10, 20, 30]));
  • Nous importons les fonctions average et std
  • Dans ce fichier, nous aurons les fonctions average et std définient dans ./stats.js

Renommer une fonction importé¶

import {std as standardDeviation} from "./stats.js";

console.log(standardDeviation([10, 20, 30]));
  • Nous importons la fonction std mais la renommons standardDeviation
  • Dans ce fichier, nous aurons toutes les fonctions définient dans ./stats.js

Importer toutes les fonctions¶

import * as stats from "./stats.js";

console.log(stats.average([10, 20, 30]));
  • Nous importons toutes les fonctions de /stats.js et les mettons dans un objet stats
  • Dans ce fichier, nous aurons toutes les fonctions définient dans ./stats.js

Exporter des fonctions d'un module¶

Dans un module, nous devons expliciter les variables (fonctions ou autre) que nous voulons exporter¶

export const INFINITY = 30;

export function average(lst){
    return 0;
}

export function std(lst){ 
    return 0;
}

La syntaxe¶

export const INFINITY = 30;
  ^       ^       ^      ^ 
  1       2       3      4
  • 1 Le mot export est réservé
  • 2 On devrait toujours exporter une constante
  • 3 Le nom de ce que nous exportons
  • 4 La valeur

La syntaxe (2)¶

export function average(lst){
    return 0;
}
  • export, on a compris, le mot "export" est magique

Export defaults¶

Problème¶

  • Il y a des modules qui veulent exporter une seule chose
    • connecteur à une base de donnée
    • mithril

Terminologie¶

  • "default" (adject)

Bibliographie¶

  • Une super BD https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/

  • La vraie doc: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules

  • V8 (aka google) https://v8.dev/features/modules

Programmation Client II¶

Les Dates¶

Quelle heure est-il?¶

C'est difficile en bâtard¶

  1. Il est 6h00PM
  1. Il sont fou ces américains... Il est 18h00
  1. Mais où? Il est 18h00 à montréal
  1. S'il est 18h00 à montréal, je suis incapable de dire quel heure il est à Saint-Petersbourg sans parler de data (merci à l'heure d'hiver). Donc, il est 18h00 à montréal le 7 decembre 2023

Fait: les dates et heures c'est vraiment compliqué¶

  • https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca

Solutions à la complexité (pas vraiment)¶

L'heure UTC (Coordinated Universal Time) (temps universel coordonné)¶

  • Le fuseau horaire préféré des programmeurs

UTC est une échelle de temps comprise entre le temps atomique international (TAI) qui est stable mais déconnecté de la rotation de la Terre et le temps universel (TU), directement lié à la rotation de la Terre et donc lentement variable.

Dans « Temps Universel Coordonné » UTC, le terme « coordonné » indique que ce temps s’écoule de façon identique à celui du Temps Atomique International, il en a la stabilité et l’exactitude à un nombre entier de secondes près, et grâce à un mécanisme d'ajustement mis en œuvre chaque fois que nécessaire, il est décalé d'une seconde pour qu'il reste proche du temps universel à moins de 0,9 s près.

-- wikipedia

Points¶

  • Les serveurs sont habituellement en temps UTC

  • Les navigateurs sont habituellement en temps locale

Fuseaux Horaires¶

  • Les fuseaux horaires se comparent à UTC zero (aka, heure de londres en hivers)

  • https://fr.wikipedia.org/wiki/Fuseau_horaire

Los Angeles, États-Unis (UTC-8) : 04:00
Chicago, États-Unis (UTC-6) : 06:00
New York, États-Unis (UTC-5) : 07:00
Halifax, Canada (UTC-4) : 08:00
Londres, Royaume-Uni (UTC±0) : 12:00

Heure Unix (Unix epoch time)¶

L'heure Unix ou heure Posix est une mesure du temps fondée sur le nombre de secondes écoulées depuis le 1er janvier 1970 00:00:00 UTC, hors secondes intercalaires. Elle est utilisée principalement dans les systèmes qui respectent la norme POSIX1, dont les systèmes de type Unix, d'où son nom. C'est la représentation POSIX du temps.

Fait: On veut pleurer...¶

Ce que javascript nous offre?¶

Heure Unix¶

  • On peut demander à javascript quelle est l'heure UNIX

  • Ce que javascript nous retourne est un nombre en milli secondes

let unixTimestamp = Date.now();
console.log(unixTimestamp) // 1701713417357

Ça nous aide? oui mais pas tout le temps¶

  • Ça peut nous aider à calculer le durée entre deux événements

  • Mais, sincèrement, quelle est l'heure à 1701713417357?

Donc, on va construire une "instance"¶

let date = new Date();
let dateString = date.toString();
console.log(dateString) // Mon Dec 04 2023 13:21:26 GMT-0500 (heure normale de l’Est)

Syntaxe¶

let date = new Date();
      ^     ^   ^
      3     1   2
  1. Un mot réservé qui créer une instance à partir d'une classe
  2. Le nom de la classe.
  3. L'instance de la classe
In [13]:
let date = new Date()
let dateString = date.toLocaleString();
console.log(dateString)
2023-12-04 13 h 24 min 10 s

Tout ça pour un exemple explicatif...¶

Que ce passe-t-il dans l'expression?¶

let date = new Date()
  1. Il y a le mot magique new
  2. new Date() créer un "objet" de de type Date
    1. Ici, "objet" veut dire données plus fonctions
    2. En fait, on ne veut pas les données, on veut les fonctions
    3. Nous allons appeler les fonctions d'un objet des méthodes

Les méthodes de la classe Date¶

> date.
constructor           getMilliseconds       getUTCFullYear        setYear
toString              setMilliseconds       setUTCFullYear        toJSON
toDateString          getMinutes            getUTCHours           toLocaleString
toTimeString          setMinutes            setUTCHours           toLocaleDateString
toISOString           getMonth              getUTCMilliseconds    toLocaleTimeString
toUTCString           setMonth              setUTCMilliseconds    __defineGetter__
toGMTString           getSeconds            getUTCMinutes         __defineSetter__
getDate               setSeconds            setUTCMinutes         hasOwnProperty
setDate               getTime               getUTCMonth           __lookupGetter__
getDay                setTime               setUTCMonth           __lookupSetter__
getFullYear           getTimezoneOffset     getUTCSeconds         isPrototypeOf
setFullYear           getUTCDate            setUTCSeconds         propertyIsEnumerable
getHours              setUTCDate            valueOf
setHours              getUTCDay             getYear

La documentation de la classe Date¶

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Exercices¶

  1. Quelle heure est-il localement?

  2. Quelle mois sommes-nous présentement? Écrire le mois mot.

  3. Quelle année sommes-nous?

  4. Quel est l'époch time présentement (en seconde)?

  5. Quelles minutes dans l'heure est-il présentement?

  6. Dans quel fuseau horaire vous trouvez vous présentement (en heure par rapport à UTC-0)?

  7. Quelle est l'epoch time dans exactement 1 an?

  8. Quelle était l'époch time à ce moment exact le mois passé?

Programmation Client II¶

La programmation orienté objet¶

Objectif: caché les données¶

Objects hide their data behind abstractions and expose functions that operate on that data. Data structures expose their data and have no meaningful functions.

-- uncle bob

En français¶

On veut avoir un paquet de méthodes toutes lié entre elles qui gère les mêmes données.

C'était exactement ce que nous avons fait avec la Date¶

let date = new Date();
      ^     ^   ^
      3     1   2
  1. Un mot réservé qui créer une instance à partir d'une classe
  2. Le nom de la classe.
  3. L'instance de la classe

Et si on y pense...¶

let date = new Date();
date.setFullYear(2024);
console.log("L'époch time dans 1 an sera exactement " + date.getTime() + " ms");

Ici, l'instance date "cache" plein de choses

  • le fuseau horaire
  • l'heure
  • la date

C'est quoi une classe?¶

Une classe¶

Une classe représente donc une catégorie d'objets. Elle apparaît aussi comme un moule ou une usine à partir de laquelle il est possible de créer des objets ; c'est en quelque sorte une « boîte à outils » qui permet de fabriquer un objet. On parle alors d'un objet en tant qu'instance d'une classe (création d'un objet ayant les propriétés de la classe).

-- wikipedia

Une classe, est une ensemble de fonction qu'on veut associer à des données que les fonctions partagent entre elles.

Les fonctions d'une classe sont appelées méthodes. Les données de la classes sont nommées attributs.

Liens pédagogiques¶

  • https://youtu.be/RQ3ItXrULBA

  • https://youtu.be/1pYmqDnvTh8

  • https://youtu.be/WAQQ890Zudo

  • https://youtu.be/gABYMZbfGok

Exemple classique 1¶

Exemple classique 1¶

Exemple classique 2¶

Exemple pédagogique pour vrais mâles ♂️¶

C'est quoi un partie de hockey?¶

c'est deux équipes qui jouent l'une contre l'autre et qui "compte" dans le but de leurs adversaire. L'équipe qui compte le plus de but gagne la partie.

-- un expert de hockey annonyme

Didier à fait une classe pour ça...¶

https://didiercrunch.github.io/cours-420-301-ah/

In [3]:
import {HockeyGame} from "https://cdn.jsdelivr.net/gh/didiercrunch/cours-420-301-ah@006.1/modules-examples/mod.js";

let hockeyGame = new HockeyGame();
hockeyGame.awayTeamScores();
hockeyGame.homeTeamScores();
hockeyGame.homeTeamScores();
hockeyGame.awayTeamScores();
hockeyGame.homeTeamScores();
console.log(`Le gagnant de la partie est: ${hockeyGame.winner()}`)
Out[3]:
Le gagnant de la partie est: home

Une classe, c'est comme un petit language¶

  • Les données sont caché (ou devrait l'être)
  • Nous avons des méthodes pour intérragir avec la donnée

Les constructeurs¶

C'est quoi créer un objet?¶

En gros:¶

  • C'est de créer un petit sac de données
  • Ça attache les méthodes au sac
  • (et c'est pour ça que nous avons besoin du mot new)

Mais: le sac n'a pas besoin d'être vide!¶

  • Un constructeur peu prendre n'importe quoi en argument

C'est quoi un joueur de hockey?¶

C'est quelqu'un avec un prénom et un nom de famille qui est né à une date précise

-- un expert de hockey annonyme

Didier à fait une autre classe pour ça...¶

https://didiercrunch.github.io/cours-420-301-ah/

In [6]:
import {HockeyPlayer} from "https://cdn.jsdelivr.net/gh/didiercrunch/cours-420-301-ah@006.1/modules-examples/mod.js";

let player = new HockeyPlayer("didier", "amyot", new Date(1983, 9, 9))
console.log(player.currentAge());
Out[6]:
40

Un constructeur¶

La méthode constructor est une méthode qui est utilisée pour créer et initialiser un objet lorsqu'on utilise le mot clé class.

let player = new HockeyPlayer("didier", "amyot", new Date(1983, 9, 9))
              ^        ^                      ^
              1        2                      3
  1. mot clé new
  2. Méthode "spéciale" qui créer l'instance: le constructeur
  3. Les arguments du constructeur

Exercices¶

In [ ]:
 

Programmation Client II¶

La programmation orienté objet - partie 2¶

On veut créer nos classes¶

C'est quoi encore une classe?¶

Une classe, est un ensemble de fonctions qu'on veut associer à des données que les fonctions partagent entre elles.

Les fonctions d'une classe sont appelées méthodes. Les données de la classes sont nommées attributs.

Exemple, la classe URL¶

const url = new URL("https://www.example.com/personne?nom=didier&age=38");
console.log(url.hostname)  // www.example.com
console.log(url.search);   // ?nom=didier&age=38
console.log(url.pathname)  // /personne
console.log(url.pathname)  // url.protocol

Nous on veut faire la même chose!¶

Créons notre première classe!¶

La classe qui ne fait rien!¶

class Politicien{

}

const politicien = new Politicien();
  • Politicien est un peu comme l'objet vide {}
  • On ne peut rien faire avec Politicien

La classe "Paquet de fonctions"¶

class JackOfAllTrade{
   add(a, b){
       return a + b;
   }

   multiply(a, b){
       return a * b;
   }
}

Utilisation de la classe "Paquet de fonctions"¶

const jackOfAllTrade = new JackOfAllTrade();
console.log(jackOfAllTrade.add(4, 7));
console.log(jackOfAllTrade.multiply(7, 3));

Notes importante..¶

Création d'instance¶

Pour utiliser les méthodes JackOfAllTrade il faut avant, créer une instance de la classe:

const jackOfAllTrade = new JackOfAllTrade();

Utilisation d'instance¶

L'utilisation des méthodes se fait avec la convention <instance>.<méthode>

console.log(jackOfAllTrade.add(4, 7))

Focus sur écrire un méthode:¶

class JackOfAllTrade{
   add(a, b){
       return a + b;
   }
}
  1. Les méthodes sont écrites à l'intérieur de la classe

  2. La syntaxe d'une méthode est la même que celle d'une fonction... sauf sans le mot réservé function.

  3. Une méthode est "genre" une fonction

Exercices¶

  1. Écrire une classe avec les trois méthodes suivantes
    • toSnakeCase est une fonction qui convertie une phrase en snake case. Par exemple petit lapin blanc deviendra petit_lapin_blanc
    • toKebabCase est une fonction qui convertie une phrase en kebab case. Par exemple petit lapin blanc deviendra petit-lapin-blanc
    • toCamelCase est une fonction qui convertie une phrase en camel case. Par exemple petit lapin blanc deviendra petitLapinBlanc

  1. Utiliser les méthodes pour convertir la phrase on aime javascript dans les différents types

Le mot réservé this¶

Le mot réservé "this" : cas d'écode¶

Imaginons créer ajouter une méthode add2plus5 dans la classe JackOfAllTrade

class JackOfAllTrade{
   add2plus5(a){
       return (a + 2) * 5;
   }
}
  • Cette solution est "stupide" car elle n'utilise pas les méthode add et multiply déjà existantes

Le mot réservé this : cas d'écode (suite)¶

La bonne solution est la suivante.

class JackOfAllTrade{
   add2plus5(a){
       const aPlus2 = this.add(a,2)
       return this.multiply(aPlus2, 5);
   }
}
  • La on aime ça!

Définition du mot this¶

Le mot réservé this permet à une méthode d'appeler une autre méthode dans une classe!

  • vous allez beaucoup utiliser le mot this.

Exercices¶

Constructeurs et données¶

Introduction...¶

Lorsque nous appelons new Person("didier", 38) le constructeur est appelé.

  1. Le constructeur est une fonction "spéciale" qui est uniquement appelé lors de la création d'une instance

  2. Le constructeur devrait uniquement "placer" des données

  3. Le constructeur est une méthode appelé "constructor"

Exemple classique¶

class Point{
    constructor(x, y){
       this.x = x;
       this.y = y;
    }

    distanceFromOrigin(){
        return Math.sqrt(this.x * this.x + this.y * this.y);
    }
}

Utilisation de la classe Point¶

p = new Point(3, 4);
console.log(p.distanceFromOrigin());

Didier dit¶

Un constructeur ne devrait avoir que des this.chose = chose et, peut-être, des validations très simple. Tout le reste ne devrait pas être dans un constructeur

-- le meilleur programmeur au monde

Exercices¶

In [ ]:
 

Programmation Client II¶

La programmation orienté objet - partie 3¶

Language plus fortement typé¶

Faits : Javascript est un language dynamiquement typé¶

function add(a, b){
    return a + b;
}
  • La fonction add peut être appelé avec n'importe quoi
    • C'est au programmeur de s'assurer que les arguments passé a add "font du sense"

Faits : Javascript est un language dynamiquement typé¶

let x = 10;

x = doSomethingToIntegerAndReturnAString(x);

doSomethingToAString(x);
  • Le type des variable n'est pas forcément constant

  • Dans l'exemple ci-haut, x passe d'un number à un string

Opinion: Javascript a "peu" de syntaxe... mais délègue beaucoup validation au programmeur¶

Dans un programme javascript, le programmeur doit s'assurer que tous les paramêtre que les fonctions recoivent font du sense.

let x = generateX();
let y = generateY();
let z = mergeXAndY(x, y);
z = incrementZ(z);
printAll(x, y, z);

Idée de génie¶

Les "Si"¶

  • Si nous étions capable de décrire ce que les fonctions peuvent prendre en arguments
  • Si les fonctions nous décrivent ce qu'elles retourne comme valeurs
  • Si nous somme capable de décrire nos variables

Alors¶

Nous serions capable de savoir au compile time (sans executer le code) si notre programme est valide

Exemple¶

let x = generateX();      // generateX retourne un "number"
let y = generateY();      // generateY retourne un "String" 
let z = mergeXAndY(x, y); // mergeXAndY prend un "number" et 
                          // un "string" et retourne un "number"
z = incrementZ(z);        // incrementZ prend un "number" et 
                          // retourne un "number"
printAll(x, y, z);        // prend un number, un string et un number

Vérification de l'exemple¶

  • Nous pourrions écrire un programme qui vérifie que le programme "fait du sense"

Contre exemple¶

Si let z = mergeXAndY(x, y) retournait un String alors on ne pourrait pas faire z = incrementZ(z);

TypeScript¶

Présentement, le language le plus populaire pour "typer du javascript" est TypeScript:

function generateX(): number {
    return 22;
}

function generateY(): String {
    return "hello";
}

function mergeXAndY(x: number, y: String): number {
    return x + y.length;
}

function incrementZ(z: number): number{
    return z + 908;
}

function printAll(x: number, y: String, z: number): void {
    console.log(`number: ${x} , number: ${ y},  number: ${z}`);
}

let x = generateX();
let y = generateY();
let z = mergeXAndY(x, y);
z = incrementZ(z);
printAll(x, y, z);

Pratiquement, utiliser typescript require un peu (beaucoup?) de travaille¶

flowchart LR
    TypeScript --vérification--> JavaScript
    JavaScript --> Browser

OOP avec languages plus fortement typé¶

Dans les languages OOP fortement typé classiques (Java, C#,... mais surtout Java 1.1), les fonctions utilises les classes pour décrire ce qu'elles peuvent recevoir en argument et ce qu'elles retournes.

function getBestTeamName(team1: Team, team2: Team): String {

}

Probleme: utiliser une fonction avec un autre type¶

function getBestTeamName(team1: Team, team2: Team): String {

}

const les3 = new DodgeballTeam("Les 3");
const les5 = new DodgeballTeam("Les 5");

console.log(getBestTeamName(les3, les5)); // Erreur!  DodgeballTeam n'est pas un Team

Solution¶

Il faut donc être capable de dire qu'un DodgeballTeam est un Team

Sous classes¶

Continuons avec notre exemple (mais en javascript)¶

Ce que nous voulons:¶

flowchart TD
    Team --> DodgeballTeam
  1. On veut créer une classe DodgeballTeam qui est pratiquemement la classe Team plus des extra

  2. Partout où une instance de Team est acceptée, il faut qu'une instance de DodgeballTeam soit acceptée.

Construisions une classe Team¶

class Team {
    constructor(partiesGagnes, partiesPerdues){
        this.partiesGagnes = partiesGagnes;
        this.partiesPerdues = partiesPerdues;
    }

    getDiff(){
        return this.partiesGagnes - this.partiesPerdues;
    }
}

Sous-Classe DodgeballTeam¶

class DodgeballTeam extends Team {
    constructor(partiesGagnes, partiesPerdues, ballonsAttrapes){
        super(partiesGagnes, partiesPerdues);
        this.ballonsAttrapes = ballonsAttrapes
    }

    ballonsAttrapesParParties(){
        let parties = this.partiesGagnes + this.partiesPerdues;
        return this.ballonsAttrapes / parties;
    }
}

Mots clées:

extends: est le mot magique pour créer une sous classe.

Le mot réservé super¶

  • Est l'équivalent du mot this mais parle de la classe du haut.

  • this est à propos de la classe présente ou parent...

Exemple du mot super¶

class Foo {
   foo(){
       return 10;
   }
}

class Bar extends Foo{
   foo(){
       return 1000;
   }

   bar(){
       return super.foo();
   }
}

const bar = new Bar();
console.log(bar.foo()) // 1000
console.log(bar.bar()) // 10

Terminologies¶

  • sous-classe (sub-class) didier aime beaucoup ce terme. Le "sous" est entendu au point de vue mathématiques; un sous groupe d'un groupe libre est... libre!

  • super-classe (super-class) didier accepte ce terme par manque d'un meilleur terme. Le terme "super" veut dire la classe parente direct

  • classe enfant (child class) didier n'aime vraiment pas ce terme.
    Fuck la patriachie

  • classe parent (parent class) didier n'aime vraiment pas ce terme.
    Fuck la patriachie

  • polymorphisme est le concept consistant à fournir une interface unique à des entités pouvant avoir différents types. --- wikipedia

Exercices Pédagogiques!¶

Note à didier¶

  • implément les sous classes live avec les étudiants

Créer une sous-classe Carré!¶

class Rectangle {

  constructor(hauteur, largeur) {
    this.hauteur = hauteur;
    this.largeur = largeur;
  }

  aire() {
    return this.hauteur * this.largeur;
  }
}
  1. Créer une sous-classe de Rectanglenommé Carre
  2. Ajouter la méthode perimetre à Carre

Solution¶

class Carre extends Rectangle {
  constructor(cote) {
    super(cote, cote);
  }

  perimetre(){
      return 4 * this.hauteur
  }
}
  • Pour appeler le constructeur super dans une sous classe est d'utiliser super().

  • On peut façilement ajouter une fonction dans une sous-classe

Créer une sous-classe Carré!¶

class User {

  constructor(id, username) {
    this.id = id;
    this.username = username;
  }

  idAdmin() {
    return false;
  }
}
  1. Créer une sous-classe de Usernommé Admin
  2. tout admin doit être isAdmin

Solution¶

class Admin extends User {
  idAdmin() {
    return true;
  }
}
  • On peut override une méthode dans une sous-classe.

Créer une sous-classe d'animal!¶

class Animal {

  constructor() {
    this.state = "arret";
  }

  courrir() {
    this.state = "courrir";
  }

  arret() {
    this.state = "arret";
  }

  getState(){
      return this.state
  }
}
  1. Créer une sous-classe d'Animal nommé Lapin
  2. Un lapin doit être capable de se cacher
  3. Si un lapin est caché, il ne peut se mettre à courrir.

Solution¶

class Lapin extends Animal {

    constructor() {
        super();
        this.isHidden = false;
    }

    hide(){
        this.isHidden = true;
    }

    unHide(){
        this.isHidden = false;
    }

    courrir(){
        if(this.isHidden){
            return;
        }
        super.courrir();
    }
}

Note sur les solutions¶

  1. Un sous-constructeur devrait toujours appeler super

  2. Nous ne devrillions pratiquement jamais overrider une méthode

  3. Lorsque nous overriderons une méthode, nous devrillions toujours appeler la super méthode

Note importante¶

  • Tout comme les petites sections de vos brin d'ADN, une sous-classe peut avoir une seule super classe.

Deux petits "design pattern"¶

Factory!¶

On créer une fonction qui retourne différent type d'objets dépendamment de ce que la fonction prend en argument.

function getUser(loggedInRequest){
    if(request.isAdmin){
        return new Admin(request.id, request.username);
    }
    return new User(request.id, request.username);
}

instanceof¶

Pour savoir si une instance x est instance de la class Foo il faut utiliser...

let foo = new Foo();
let bar = new Bar();

foo instanceof Foo; 
bar instanceof Bar; // true ssi Bar est une sous-classe de Foo

Note poche...¶

L'héritage est un peu dépasser¶

  • Les frameworks modernes utilisent de moins en moins l'héritage

  • Les nouveaux languages de programmation ne permettent pas l'héritage

  • Les principes "SOLID" font en sorte que l'utilisation de l'héritages est assez restrain

L'héritage s'est bizzare..¶

  1. Personnellement, ça me prend énormément plus de temps lire du code qui utilise l'héritage
  2. "Mais pourquoi?" est la question principale que je me pose à propos de l'héritage
  3. L'héritage est une mauvaise manière de partager du code
  4. L'héritage en javascript est encore pire que dans des languages plus fortement typé

Exemples: React / Angular¶

  • https://react.dev/reference/react/Component

  • https://angular.io/api/core/Component

Interfaces¶

Dans les languages plus fortement typé, l'héritage à été remplacé par les "interfaces"

flowchart TD
    Team --> DodgeballTeam 
    DodgeballTeam --> MixedDodgeballTeam

Quoi faire au lieu d'utiliser de l'héritage¶

Cas d'école¶

Regardons le cas d'une équipe de dodgeball mixte. Dans une équipe de dodgeball mixte, il faut absolutment qu'au moins la moité de l'équipe soit des femmes

On commence avec la classe équipe...¶

class Team {
    constructor(partiesGagnes, partiesPerdues){
        this.partiesGagnes = partiesGagnes;
        this.partiesPerdues = partiesPerdues;
    }

    getDiff(){
        return this.partiesGagnes - this.partiesPerdues;
    }
}

Pis on renomme la classe avec un nom qui fait du sense¶

class GameStats {
    constructor(partiesGagnes, partiesPerdues){
        this.partiesGagnes = partiesGagnes;
        this.partiesPerdues = partiesPerdues;
    }

    getDiff(){
        return this.partiesGagnes - this.partiesPerdues;
    }
}
  • Lorsqu'une classe est faite pour être une super classe, souvant son nom fait aucun sense. (exemple, CoreUser, UserBase, AbstractUser, ...)

On a aussi une classe joueurs¶

class Players {
    constructor(players){
        this.players = players;
    }

    totalNumberOfPlayer(){
        let ret = 0;
        for(const player of this.players){
            if(!player.isAngered){
                ret += 1;
            }
        }
        return ret;
    }

    totalNumberOfFemalePlayer(){
        let ret = 0;
        for(const player of this.players){
            if(!player.isAngered && player.gender === "female"){
                ret += 1;
            }
        }
        return ret;
    }
}

La classe MixedDodgeballTeam...¶

class MixedDodgeballTeam{
    constructor(players, partiesGagnes, partiesPerdues){
        this.players = players;
        this.stats = new GameStats(partiesGagnes, partiesPerdues);
    }

    getDiff(){
        return this.stats.getDiff();
    }

    isValid(){
        return this.players.totalNumberOfPlayer() < 2 * this.players.totalNumberOfFemalePlayer()
    }
}

Ressources extérieures¶

Liens externes¶

  • https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Classes (très technique)

  • https://exploringjs.com/es6/ch_core-features.html#sec_from-constr-to-class (très technique)

  • https://youtu.be/2HAPViIAYjc

  • https://youtu.be/KjXBPJZPmYU

  • https://youtu.be/_cgBvtYT3fQ

Programmation Client II¶

Les Exceptions¶

In [ ]: