Je me souviens que je disais en 2010 à @Roger quelque chose du type :
La programmation fonctionnelle est un cancer.
Heureusement, dix ans plus tard j'ai quand même un peu changé d'avis sur la question, je dirais aujourd'hui :
La programmation fonctionnelle "pure" est un cancer.
La différence étant que je suis en mesure d'argumenter le ressenti inconscient que j'avais à l'époque. Depuis le bouquin sur les design-patterns du Gang of Four, nous avons eu une pléthore d'autres auteurs qui nous ont expliqué pourquoi il faut toujours dépendre des interfaces et jamais des implémentations. Le problème avec ça, c'est qu'une grande partie des développeurs ne comprennent pas bien ce que sont les implémentations et surtout pourquoi il ne faut pas dépendre d'elles.
En réalité, une implémentation embarque avec elle des attributs (et si un objet n'a pas d'attribut c'est que le développeur a codé en procédurale "pure", il n'a rien encapsulé, ça n'est pas objet du tout mais je m'égare). Le problème avec les implémentations ce sont justement les attributs qui deviennent visibles. Dit autrement nous commençons à devenir dépendant de la structure de données qui nous arrive et non plus d'un ensemble de fonctions (ie. méthodes) que nous pouvons exécuter. D'ailleurs nous sommes tellement dépendant des attributs que même s'ils sont privés, nous allons alors ajouter des getters/setters pour y accéder quand même.
Remonter à l'interface c'est casser ce lien explicite avec la structure de données embarquée dans une classe et alors un changement de structure ou de structure de la structure n'impactera pas le code utilisateur.
Mais alors quel est le problème avec la programmation fonctionnelle "pure" ?
C'est justement qu'elle pousse tous les morceaux de code à dépendre des mêmes structures. Changez la structure à un endroit et vous êtes partis pour changer toutes les fonctions qui s'appuient sur cette structure. Cela engendre fondamentalement un maillage global de tous les pans de code d'une application avec un couplage fort autour de cette ou de ces structures.
La seule condition pour y remédier c'est d'avoir "la bonne structure du premier coup"... lol quoi... Comment prévoir quelles données (et de quels types) nous arriveront demain ?
À l'inverse, retourner des implémentations d'interface autoboxé dans le type de cette interface (c-à-d. les fameux "messages" de la POO) garanti non seulement que les changements de structures n'auront pas d'impact, mais que les changements d'algorithmes non plus (ici "pas d'impact" est à prendre au sens où le contrat d'interfaçage n'est pas rompu et donc que le code continu de compiler).
Pourquoi est-ce que je vous parle de tout ça ?
À cause Rust et de mes quatre semaines d'immersion intense.
Soyons clair, je trouve que les concepts derrière le langage sont incroyables et ses performances merveilleuses (en tant que dev Java j'ai toujours détesté la JVM rien que pour ce sujet). Par contre le fait que Rust se soit tourné exclusivement vers le fonctionnel et la programmation en "structure-first" à la place de celle en "contract-first" car la majorité des devs ne parviennent pas à penser en objets avec l'encapsulation, cela fait de Rust un langage aussi immaintenable que C mais un peu plus fiable grâce à son meilleur compilateur.
L'API de Rust est digne de celle du C. Par exemple, prenons la méthodes HashMap::keys()de la stdlib de Rust. Celle-ci aurait pu retourner l'implémentation d'un trait Iterator mais non, elle retourne une structure Key qui contient une structureIter qui contient une autre structure base::Iter.
Changez un morceau de la chaîne et préparez-vous à gérer les impacts partout.
En résumé, et après être passée dans l'ordre par Java, OCaml, PHP, C, ASM, Bash, CSH, Python, JavaScript (ES5 à ES7), Anubis, Haskell, Ruby, Groovy, TypeScript, Scala, Go, Kotlin et enfin Rust (ndr. je bidouillais en Rust depuis quelques années), je peux vous assurer que :
- Rust est techniquement un super langage avec l'un des meilleurs compilateur du marché.
- Rust a une API aussi pourrie que celle de C, encourageant le couplage et augmentant l'immaintenabilité. Je crois qu'il doit exister un moyen d'outre-passer cela, mais je ne sais pas encore comment faire et ça me fruste pas mal.
Enfin, je sais que certains dev vont être fâchés de lire ce que j'écris alors permettez-moi de vous proposer un test car j'ai le sentiment que si c'est le cas, c'est que vous n'avez jamais pensé en OOP - et donc que vous ne pouvez pas encore comprendre ce que je dis. Il s'agit d'un exercice que @Kysofer a imaginé pour ses entretiens d'embauche afin de savoir si un candidat "expert Java" savait penser et programmer en orienté objet.
Prenez ces deux classes :
class Person {
private final String name;
private final String firstName;
private final int age;
public Person(String name, String firstName, int age) {
this.name = name;
this.firstName = firstName;
this.age = age;
}
}
class Car {
private final String brand;
private final String name;
public Car(String brand, String name) {
this.brand = brand;
this.name = name;
}
}
Objectifs :
- Sans violer l'encapsulation, c'est-à-dire sans jamais accéder aux attributs des deux classes depuis l'extérieur de ces deux classes.
- Sans ajouter des getter ou des setter.
- Sans mettre les attributs en public, package ou protected.
- Sans implémenter les algorithmes de conversion à l'intérieur des deux classes elles-mêmes.
=> Écrivez une architecture qui soit capable de convertir en JSON ou en XML ces deux objets.
Indice : Quand on pense en objet, c'est évident, très facile même. Quand on ne pense qu'en procédurale ou son évolution en fonctionnel, cela paraît impossible.
Et dans tout ça je ne compte pas arrêter Rust pour autant mais je fais appel à mes amis pour qu'ils m'aident à trouver une façon "clean" de coder dans ce langage.
Pour toi @Animal, une explication des méthodologies de gestion des risques.
Je viens de percuter qu'en Rust, les TU sont dans le même fichier que celui du source à tester à ceci près qu'ils sont dans un module appelé tests... J'ai failli vomir sur le coup !
On a quand même bientôt 20 années de Maven et Gradle, ou de Composer et Symfony, ou encore presque une décennie de npm/yarn et Karma, de rake et Ruby, de pyb et Python ; et des gens n'ont toujours pas compris qu'il y avait une différence entre les sources qu'on livre et celles qui servent à fabriquer les sources qui vont être livrées. De la même manière qu'il ne faut pas générer les binaires dans le répertoire ./src il ne faut pas mélanger le code de ses TU avec celui de son programme, idem pour les ressources des tests et du programme.
Il n'y a pas à dire, l'univers des langages bas niveau (C/C++/Rust/Go/etc) est d'une pauvreté en terme de méthodologie, c'est incroyable ! D'autant qu'une bonne partie des personnes y œuvrant se prends systématiquement pour des cadors, j'ai de la peine pour eux et encore plus pour ceux qui doivent faire avec...
Bref, pour des raisons évidentes d'hygiène je vais détourner le répertoire des TI en TU si c'est possible de le faire...
EDIT : l'arborescence standard d'un projet Rust.
.
├── Cargo.lock
├── Cargo.toml
├── src/
│ ├── lib.rs
│ ├── main.rs
│ └── bin/
│ ├── named-executable.rs
│ ├── another-executable.rs
│ └── multi-file-executable/
│ ├── main.rs
│ └── some_module.rs
├── benches/
│ ├── large-input.rs
│ └── multi-file-bench/
│ ├── main.rs
│ └── bench_module.rs
├── examples/
│ ├── simple.rs
│ └── multi-file-example/
│ ├── main.rs
│ └── ex_module.rs
└── tests/
├── some-integration-tests.rs
└── multi-file-test/
├── main.rs
└── test_module.rsJe viens de trouver l'animé pour toi @Animal :
Tatsuhiro Satô est un hikikomori c'est à dire une personne qui préfère rester enfermée chez elle plutôt que de vivre en société. Cela fait déjà trois ans qu'il est resté enfermé chez lui à réfléchir et il en est arrivé à la conclusion que sa situation est dû à un complot de la NHK (chaîne de tv japonaise) afin de créer plein d'hikikomori. Il décide alors de lutter contre cette conspiration et de sortir de chez lui mais c'est pas toujours facile pour un hikikomori.
... Message... :)
MERCI ! Je suis en train de me battre chez mon client actuel pour pousser du no-estimate. Je leur avais sorti plein de façons d'estimer à moindre frais en m'appuyant sur le contenu des conférences de @Chlouchloutte, notamment celle portant sur la Sociologie du Management et l'autre sur l'Historique de la Structuration des Organisations.
J'en étais même venue à faire de la fouloscopie et imaginer avec @Kysofer des techniques d'estimation par intelligence collective (comme l'explique Mehdi Moussaid dans l'une de ses conférences) et pourtant impossible de faire changer d'avis les décideurs : il faut estimer et estimer précis !
Ce qui m'intéresse dans cette étude c'est qu'à 61%, et quelque soit le degré d'expérience, les estimations seraient fausses. C'est un argument de poids pour moi !
Merci encore une fois Chezsoi pour le lien.
Sur une idée de @Kysofer, je reprends mon post précédent pour mettre à jour l'exemple que j'avais donné afin de l'améliorer et de le simplifier.
L'idée est de se débarrasser des méthodes 'static' de chaque structure que j'avais appelées "new" pour les remplacer par des fonctions globales (globales au niveau du module) à côté des structures et dont le nom est plus porteur de sens. (ndr. elles remplacent les constructeurs nommés de Yegor Bugayenko en prenant un petit peu de la Factory Method défendue par Joshua Bloch).
L'intérêt des d'avoir des objets concrets qui profitent tout de suite du polymorphisme d'une interface (ici "Addition") et de wrapper ces instances dans une Box<dyn T> pour être réutilisées ailleurs, y compris dans une struct. Cela découple totalement les liens entres les instances puisque seules les types des interfaces fuitent.
Si à cela on ajoute l'immutabilité totale et l'absence de getter/setter, alors cela commence à être du vrai FOP (Functional-Object Programming) dont la base s'appuie sur la notion d'Elegant Objects.
Je suis contente de savoir à présent allier parfaitement paradigmes fonctionnel et objet alors qu'ils m'ont toujours été présentés comme deux antagonistes.
L'étape suivante sera de compléter l'exemple pour effectuer le même calcul en multi-thread et tirer 100% de la puissance de Rust. @Kysofer, si tu as l'envie de m'aider :P
#![allow(non_snake_case)]
// Exécution
fn main() {
let additionA = AdditionFromCouple(1, 2);
println!("Couple add : [{}]", additionA.add()); // Print 3
// Ne pas oublier de wrapper Couple dans une Box
let additionB = AdditionFromTriplet(additionA, 3);
println!("Triplet add : [{}]", additionB.add()); // Print 6
}
// Traits
trait Addition {
fn add(&self) -> i32;
}
// Structures
struct Couple {
opA: i32,
opB: i32,
}
struct Triplet {
opA: Box<dyn Addition>,
opB: i32,
}
// Implémentations
impl Addition for Couple {
fn add(&self) -> i32 {
return self.opA + self.opB;
}
}
impl Addition for Triplet {
fn add(&self) -> i32 {
return (*self.opA).add() + self.opB;
}
}
// Factory Methods (Utilisées comme constructeurs)
fn AdditionFromCouple(opA: i32, opB: i32) -> Box<dyn Addition> {
return Box::new(Couple { opA: opA, opB: opB });
}
fn AdditionFromTriplet(opA: Box<dyn Addition>, opB: i32) -> Box<dyn Addition> {
return Box::new(Triplet { opA: opA, opB: opB });
}Je reprends l'exemple que j'avais donné ici et que j'ai modifié pour le "Yegorifier".
#![allow(non_snake_case)]
// Interface / Trait
trait Addition {
fn add(&self) -> i32;
}
// Couple
struct Couple {
opA: i32,
opB: i32,
}
impl Couple {
// Équivalent à une méthode 'static' de Java simulant un constructeur
fn new(opA: i32, opB: i32) -> Self {
return Couple { opA: opA, opB: opB }
}
}
// Triplet
struct Triplet {
opA: Box<dyn Addition>, // Un trait doit être passé dans un objet de type Box
opB: i32,
}
impl Triplet {
// Équivalent à une méthode 'static' de Java simulant un constructeur
fn new(opA: Box<dyn Addition>, opB: i32) -> Self {
return Triplet { opA: opA, opB: opB }
}
}
// Implémentations du trait "Addition"
impl Addition for Couple {
fn add(&self) -> i32 {
return self.opA + self.opB;
}
}
impl Addition for Triplet {
fn add(&self) -> i32 {
return (*self.opA).add() + self.opB;
}
}
// Exécution
fn main() {
let additionA = Couple::new(1, 2);
println!("Couple add : [{}]", additionA.add()); // Print 3
// Ne pas oublier de wrapper Couple dans une Box
let additionB = Triplet::new(Box::new(additionA), 3);
println!("Triplet add : [{}]", additionB.add()); // Print 6
}Comment faire sauter l'activation d'un Windows XP (ou tout autre OS pour lequel Microchiotte a arrêté ses serveurs, quand on vous que le libre vous protège).
Sinon je suis toujours sur mes tentatives de faire marcher StarCraft sous Linux, la version "normale" ne parvient pas à switcher en affichage 8-Bits sous Wine, la version "remastered" n'est juste pas prise en compte #PureSadness
D'autant que j'avais acheté la version "cartooned" pour mes petits :(
Au passage si quelqu'un sait comment je peux demander à Xephyr d'être en plein écran avec une résolution 640x480 je prends !
Tout est dans le titre.
Je suis tombée par hasard sur Starcraft Remastered. Je n'étais pas très douée pour Starcraft & Broodwar mais le fait de découvrir un jeu de mon enfance en HD m'a donné tout de suite envie de l'acheter (surtout la version cartoonned pour jouer avec mes petits).
Note à moi-même : ne plus jamais acheter de jeux Blizzard à l'avenir. Ces abrutis nous forcent à installer un installeur qui téléchargera et exécutera l'installeur des jeux... Installeur qui n'existe pas sous Linux forcément.
Sous Linux c'est une catastrophe. #Déception
@OpenNews lol on ne s'est peut-être pas compris.
L'argument de scandinave (qui m'avait touché) n'était pas de défendre ou d'attaquer les médias ou les réseaux sociaux pour prétendre qu'untel est meilleur ou moins bon que l'autre mais de montrer à travers ses deux exemples - qu'il a volontairement rendu grossiers afin d'illustrer sa pensée - que la notion de vérité n'existe pas en tant que valeur absolue et c'est en ce sens que j'ai repris son post.
Denzel Washigton l'explique très durant les 30 premières secondes de cet extrait que je peux synthétiser/traduire en ceci :
Si vous ne lisez pas la presse alors vous n'êtes pas informé mais si vous lisez la presse alors vous êtes désinformé. [...] Quels sont les conséquences à long termes d'un excès d'information ? [...] Les médias actuels tentent d'êtres les premiers [ndr. à sortir une news] pas de rapporter la vérité [...]
C'est pour cela que j'ai rebondis sur son post car je crains la création d'un "ministère de la vérité" mais qui s'instaurerait de manière insidieuse et quasiment invisible via des articles du genre de celui sur lequel répondait scandinave. Cela a déjà commencé en France avec le Decodex du Monde qui s'était attaqué au site les-crises.fr sans fondement, juste parce que les sites de "fact-checking" ne sont ni plus ni moins qu'un support permettant d'encourager les citoyens à écouter et croire quelques uns au détriment d'autres et ceci sans la moindre preuve, seulement en les pointant du doigt.
D'ailleurs le youtubeur Trouble Fait l'explique parfaitement dans sa vidéo Fake News : L’assaut de la police de la pensée (31 min à voir, foncez) en dénonçant le grand retour du Maccarthysme.
Pour reprendre les propos de l'article, ok admettons que les gens qui dépendent des réseaux sociaux sont moins bien informés (sous-entendus que ceux qui dépendent des grands médias, grands médias qui sont détenus - à perte - par une poignée de milliardaires hein). Mais quel est le critère ? Quelle est l'unité ? Comment se font les mesures permettant de dire que quelqu'un est plus ou moins bien informé qu'un autre !? Une ligne politique ? Une doctrine religieuse ? Une morale "vertueuse" ? lol
La critique de scandinave montre de manière subtile que l'article posté sur developpez.com est un article politique, basé sur une pseudo-étude dont la rigueur est à la science ce que l'homéopathie est à la médecine.
Bref, j'aurai dû être plus explicite dans ce que je souhaitais mettre en exergue dans mon post d'origine. En tout cas merci à toi qui a pris le temps de me lire et de me répondre.
Je cite le post de scandinave :
Informé par rapport à quoi? qu'est-ce qu'une "fake news"? Si je prend l'exemple français récent. Micheline, 50 ans ne s'informe que sur les canaux officiels ( TV, Radio, Journaux ). Qu'est qu'elle à entendu depuis 2 ans ?
- Les Gilets jaune sont des terroristes Brun-Rouge antisémite.
- La France est en faillite, il faut détruire les retraites.
- Les profs sont des feignants.
- Les cheminots des privilégiés.
- Le personnel hospitalier des râleurs qui ne voit pas la chance qu'ils ont et ne comprennent pas qu'il n'y à pas d'argent magique.
De l'autre coté, Bastien, 20 ans, ne lit pas le journal, n'écoute pas la radio et ne regarde presque jamais la TV. Lui il s'informe sur Facebook, Youtube, Twitter, des blogs ... .Qu'a-t-il pu voir ?
- Des témoignages d'amis Gilet Jaune s'en prenant plein la gueule en manif. Des émissions expliquant en détail leurs revendications ( Justice Sociale, Fiscale, RIC ... )
- Des émissions d'économiste atterrés expliquant que non la France se porte bien et qu'il n'y à aucune raison de toucher au système de retraite.
- Lire des blogs de profs ( https://cyrille-borne.com/ ) partageant leurs quotidiens et montrant que la majorité est loin d'être feignante.
- S'apercevoir que le salaire des cheminots est pas si élevé que cela. Surtout en rapportant cela au contrainte du métier ( Amplitudes horaires, astreintes, risque d'agression, ... )
- Voir dans quel état d’impréparation et de manque les hôpitaux se trouvaient quand le covid est arrivé et que finalement le personnel soignant ne faisait pas que de se plaindre pour rien.
Bref, je pense que vous avez compris l'idée. Je vous laisse déterminer suivant votre obédience politique, lequel à le plus mangé de "fake new" et lequel est "le mieux informé". Cela ne veut pas dire que Bastien ne pourra pas se limiter qu'a des théories fumeuses sur Facebook ou que Micheline, ne sera pas à même de démêler le vrai du faux. Cela veut juste dire que cette étude ne sert à rien.
J'ai très peu de choses à ajouter à cet argumentaire. Peut-être une conversation que j'ai entretenu avec ma moitié et qui me disait (de mémoire, tu me corrigeras) que la première partie du mandat de Macron visait à privatiser tout ce qui touchait à la cohésion d'état (sécu, retraite, santé, éducation, routes, aéroports, etc), la seconde visera à brimer tout ce qui est incontrôlable (en premier lieu internet avec la censure et la rue avec les forces de l'ordre-par-la-force).
La loi Avia était une première attaque, ce gouvernement s'appuiera sur tout ce qui touche à l'émotionnel pour faire passer ses anti-lois (BLM, progressisme, PMA / GPA, etc). Toutes les ébauches de bons sentiments seront mises en avant comme autant d'opérations psychologiques qu'il en faudra pour amener la France là où elle devra être : un état à mi-chemin entre le modèle ultra-libéral allemand sans entre-aide et le contrôle violent et omniprésent chinois.
Alerte au gogol ! Alerte au gogol les enfants

Boursorama en ajoutant des trackers de serveurs de pub sur son site permet à des sociétés tierces d'accéder aux comptes de ses clients. Bravo, zetes des champions...
C'est un scandale, information à faire tourner autant que possible en espérant que le bad-buzz leur serve de leçon !
Cela faisait quelques temps que je me demandais quel ORM choisir pour remplacer ActiveJDBC car ce dernier est très bien mais je souhaitais un framework qui accentue d'avantage l'OOP.
D'ailleurs ActiveJDBC avait remplacé depuis bientôt 5 ans maintenant Hibernate & OpenJPA chez moi, car eux-mêmes étaient beaucoup trop orientés procédurale (@Sweet clin d’œil à ce sujet) au point de rendre impossible de respecter le principe d'encapsulation et aussi parce que l'usage intensif de l'API réflexion par Hibernate ne permet pas la compilation en natif via GraalVM.
Bref, j'hésitais entre trois frameworks et je pense que je vais partir du Ktorm qui a une super doc, de bonnes performances et une façon très simple de requêter la base :

J'ai sorti Kuery car il n'est plus maintenu depuis trois ans et qu'il lui manque certaines fonctionnalités et j'ai aussi mis de côté Exposed car trop orienté fonctionnel et donc incitant à violer l'encapsulation à l'image d'Hibernate.
Bref Ktorm est dans le pipe.
@Sweet le 9 c'est le plus compliqué quand on vient du procédurale et qu'on essaie de faire de l'OOP (note : l'API Java est procédurale à 99%).
Je l'ai compris grâce à des formations que des copains d'ITAMETIS m'ont offertes (merci @Kysofer pour tout le temps que tu as passé à m'appendre). En substance, dès qu'une classe affiche un getter ou un setter, alors son développeur a violé le principe d'encapsulation, ce qui est "anti-objet" par nature.
Dit autrement, nous mettons des get/set pour avoir bonne conscience mais nous pourrions les remplacer par des attributs public cela reviendrait exactement au même. En ajoutant des getter/setter nous exposons deux choses en les sortant de l'encapsulation :
- La valeur de la donnée
- Le type réel de la donnée (c'est de loin le pire)
Et ce type d'objets s'appelle : une structure de données. Les méthodes des autres objets appelant les get/set n'étant que des procédures décidant quoi mettre et quoi retirer de ces objets structures de données.
Alors cela m'a pris un bon moment avant de comprendre comment coder sans setter (pour l'immutabilité de la programmation fonctionnelle) et sans getter (pour respecter l'encapsulation de la programmation orientée objets) ; et bien sûr sans jamais remplacer l'un ou l'autre par des attributs publics. C'est ce que j'entends lors que j'écris "programmer en interface-first".
Le meilleur bouquin que je puisse te recommander à ce sujet est Elegant Objects de Yegor Bugayenko. C'est un solid 5/7 au niveau de la "disruptivité". Mais si tu fais du Java par exemple, alors tu devrais comprendre pourquoi ceux qui font "du vrai" OOP (pardon pour l'expression mais c'est à prendre au sens "ne violant jamais l'encapsulation") disent que Spring n'est pas orienté objet pour un sou et que le framework pousse à de la programmation procédurale comme en C ou VB.
Après c'est mon côté coach crafts qui incite toujours à mieux comprendre un paradigme de programmation et d'expérience maintenant, la grande majorité des développeurs ne creusent pas plus loin que les 75% d'un concept (ça descend en dessous des 20-25% pour l'objet et le fonctionnel car les "frameworks s'en occupent pour nous") et puis il faut aussi admettre que le procédurale est bien plus accessible quand on veut produire vite, même s'il est nettement moins maintenable.
C'est la première fois que j'entends Bruno Le Salé parler ouvertement de la lutte des classes et j'aime ça ! Je regarde de temps en temps ses vidéos, lui et moi n'étant pas des mêmes bords en politique, c'est souvent difficile de l'écouter mais comme il est un troll dans l'âme et que j'ai grandi entourée de trolls depuis l'enfance, j'arrive à passer outre et à m'en divertir assez facilement.
Depuis quelques temps, il se lance dans l'analyse et même si ça n'est pas parfait, c'est toujours 100 fois + une mieux que BFM TV à mon humble avis. La vidéo vaut le coup d’œil dans le sens où elle recontextualise le mouvement BLM vis-à-vis des enjeux gravitant autour de l'élection présidentielle américaine, des intérêts financiers présents derrière et du fait que le présumé pédophile (selon internet) le tendancieux Joe Biden remonte en flèche dans les sondages face à Trump.
Bref, je vous invite à écouter / regarder cette vidéo. Par contre je colle à Bruno Le Salé un petit -1 pour la flemme qu'il a eu de mettre les sources en commentaire de vidéo (même si comme il le dit lui-même, celles-ci figurent en incrustation dans la vidéo).
J'avais entendu le nom il y a quelques années mais n'ayant pas plus creusé le concept je l'avais oublié. Le hasard du destin me fait retomber dessus aujourd'hui. Bref il s'agit de 9 règles de programmation à appliquer.
En résumé :
- N'utiliser qu'un seul niveau d'indentation
- Ne pas utiliser le mot-clef ELSE
- Encapsuler toutes les primitives et les String dans des objets
- Encapsuler les collections dans des objets
- N'enchaîner qu'un seul point (ou flèche) par ligne
- Ne pas utiliser d’abréviations
- Garder des classes petites (moins de 50 lignes)
- Aucune classe ne doit avoir plus de deux instances en guise de variables
- Ne jamais utiliser de Getter/Setter
Globalement, je le fais sans m'en rendre compte, mes classes sont minuscules (20 lignes en moyennes). Éventuellement le ELSE m'est encore utile mais c'est vrai que programmant en fail-first je lui préfère un throw direct et donc qu'il n'apparaît vraiment pas souvent.
Bon cela faisait quelques temps que je souhaitais ouvrir un compte ailleurs et j'étais plus que tentée par la N26. Aujourd'hui je me réveille enfin motivée et j'y vais, je me lance ! (^__^)/
Première impression : tout est facile, créer un compte est facile, choisir un mot de passe est facile, se déclarer est facile. D'ailleurs enfin une banque qui ne vous impose pas un code pin minable à chiffre sur un clavier virtuel pété pour sécuriser vos comptes faire de la merde comme toutes les autres.
Et puis je m'arrête à la dernière étape car bloquée ! But WHYYYYYY ??? (T_T)
Parce que la banque impose à ses clients une "appli-mobile" pour finaliser leur inscription, "appli-mobile" qui ne peut se récupérer QUE depuis le Google Play Store ou l'App Store. Or je me suis dégooglisée il y a bien longtemps et plutôt crever que d'y retourner.
Après je me dis que j'ai les moyens de m'acheter un téléphone bidon et de l'associer au forfait Free à 0€/mois donc pourquoi pas ? Et puis je commence à lire les CGU... Et là c'est le drame...
On est en 2020 et la N26 gère sa sécurité en liant votre compte à votre mobile... Je vais le dire autrement :
- Votre mobile casse => plus aucun accès à vos comptes.
- Votre mobile est volé => plus aucun accès à vos comptes.
- Votre mobile tombe en panne => plus aucun accès à vos comptes.
- Votre mobile est télé-bloqué => plus aucun accès à vos comptes.
Vous comprenez, ce n'est pas le numéro de mobile mais le périphérique lui-même qui est attaché au compte... Périphérique que nous laissons traîner partout et bien souvent à la durée de vie minime...
Ce fût donc un beau et merveilleux NO GO pour N26 (à la toute dernière étape) parce que la banque-mobile n'est pas capable en 2020 de permettre à ses clients de passer par un site web. D'autant que faire une web-app hybride Android / iOS ça ne coûte rien avec du PhoneGap + Aurelia/React/Angular/Vue/Nimporte-quelle-techno-à-la-mode.
Bref, j'avais pas mal d'argent à leur donner dommage pour eux. En même temps je n'ai pas été très maligne car en lisant l'appellation "banque-mobile" à aucun moment je ne me suis imaginée que la banque n'était QUE sur mobile... Je n'arrive pas bien à comprendre la logique derrière qui consiste à se fermer un marché mais admettons.
P.S : félicitation à Daniel de leur support qui a été d'une grande patience avec moi aujourd'hui.
Note personnelle : je n'aime vraiment pas du tout la syntaxe de Rust, mais vraiment :(. À chaque fois que j'en fais je meurs un petit peu. Après je maintiens qu'il s'agit d'un des meilleurs langages du marché à cette heure et une tendance de fond qui me pousse à prendre la vague.
Bon je vais reprendre le début du kata @Kysofer (qui va me faire intervenir dans ses formations) pour montrer comment il programme en OOP "pure" avec Rust en mettant en place une encapsulation stricte (à la Yegor Bugayenko). Le poste se fera en plusieurs parties, cette première étape consistant à montrer comment fonctionnent les trait, les struct et la notion de value borrowed pour les débutants.
Objectifs du kata :
- Fournir deux structures différentes permettant l'addition.
- Décorer la première structure par la seconde.
- Introduction succincte au
value borrowed.
Code :
#![allow(non_snake_case)] // Oui je viens du monde Java/Kotlin
// Structures
struct Couple {
opA: i32,
opB: i32,
}
struct Triplet {
opA: Couple,
opB: i32,
}
// Interface
trait Addition {
fn add(&self) -> i32;
}
// Implementations
impl Addition for Couple {
fn add(&self) -> i32 {
return self.opA + self.opB;
}
}
impl Addition for Triplet {
fn add(&self) -> i32 {
return self.opA.add() + self.opB;
}
}
Exécution :
Pour instancier et exécuter le code il faut écrire ceci. Tout marche, aucun problème.
fn main() {
let additionA = Couple { opA: 1, opB: 2 };
println!("Couple add : [{}]", additionA.add()); // Print 3
let additionB = Triplet {
opA: additionA,
opB: 3,
};
println!("Triplet add : [{}]", additionB.add()); // Print 6
}
La petite difficulté (el famoso "value borrowed") arrive dès que l'on initialise les deux structures l'une derrière l'autre :
fn main() {
let additionA = Couple { opA: 1, opB: 2 };
let additionB = Triplet {
opA: additionA,
opB: 3,
};
println!("Couple add : [{}]", additionA.add()); // NE COMPILE PAS
println!("Triplet add : [{}]", additionB.add());
}
En réalité, au moment du premier println!(), la variable additionA n'est plus dans l'espace courant mais a été empruntée par Triplet, elle se retrouve donc utilisable mais uniquement par lui. Alors soit on réordonnance le code (ce que j'ai fait dans la première exécution qui fonctionne) soit on indique que Triplet restitue la variable qu'il a emprunté (je montrerai plus tard comment faire).
Bref, jusque là rien de transcendant nous remarquerons quand même que Triplet contient un Couple (c'est-à-dire une structure) et non une Addition (c'est-à-dire une interface) ce qui matérialise un couplage fort entre les types et donc l'impossibilité de programmer par contrat (c'est-à-dire en masquant les implémentations et en protégeant l'encapsulation des données contenues dans la structure Couple).
C'est là qu'arrivera la second difficulté dont je parlerai aussi plus tard : comment calculer dynamiquement les tailles des implémentations des traits pour les utiliser en tant qu'attribut d'une structure.
Avis personnel : depuis quelques mois que je m'amuse avec Rust je peux dire que globalement j'aime ce langage mais cela ne m'empêche pas de le trouver pauvre sur pas mal de ses aspects (au sens paradigme de programmation).
Dans ce qui me déplaît, je mettrais la forte emprunte qu'il retire C et du C++, notamment leur style procédurale omniprésent (on ne code plus comme en Pascal en 2020, damned), l'encapsulation découragée totalement (en ce sens Rust n'est pas objet pour un sous, et la programmation en structure-first est un anti-concept, encore une fois cf. Elegant Objects de Yegor Bugayenko) et pour ma plus grande tragédie, une syntaxe que je trouve lourdingue car s'appuyant sur beaucoup de symboles ou trop peux expressive (je suis navrée pour ceux qui pensent que i32 et u32 sont de bonnes façons d'écrire des entiers signés ou non en 2020).
Encore une fois, la syntaxe de Kotlin (sauf le sucre syntaxique du préfixe get/set et les equals methods), l'API immutable de Kotlin, la gestion des Threads/KoRoutines de Kotlin, le null-check de Kotlin, le tout mêlé au Owernship de Rust, à la performance du binaire produit par son compilateur, à sa capacité à gérer du bas niveau, tout ceci en ferait sûrement l'un des langages les plus efficaces et fiable du siècle.
Je prie pour que Kotlin Native soit un "game changer" notamment pour qu'il parvienne à s'élever au niveau de Rust en terme de performances et de protection contre les race-conditions.
Je me le note, merci à JcFrog pour le lien.
Sans blague... Utiliser un des compilateurs les plus difficiles du marché (ici Kotlin) prévient une grande partie des bugs et réduit leur nombre de 33%, le cas présent sur l'application Google Home depuis Que Goole a remplacé le code en Java par Kotlin.
C'est un peu comme si les langages interprétés et sans contrôles ultra-stricts à la compilation étaient moins efficaces... La surprise est totale ! (Ô__Ô) #Kotlin #Rust
Tiens j'entends comme un écho qui dénigrerait Python... Et quelqu'un d'autre qui tousse très fort JS/NodeJS... Vraiment bizarre, allez savoir pourquoi #TrollInsideOuPas