Montrez-moi une solution à cause de laquelle les développeurs ne discuteront pas, et je vous mettrai une bière



Il y a deux camps inconciliables. Certains disent: vous devez décrire avec précision et compétence vos engagements. Chaque validation est un travail complet et significatif. Si vous ne pouvez pas faire une description claire et simple d'un commit, alors vous avez les mauvais commits.

D'autres considèrent que vous effectuez des commits comme vous le souhaitez, cela fait partie de votre flux de travail personnel. Mais l'ensemble des demandes est décrit en détail: ce qui est fait, comment est fait, pourquoi est-il fait. Comme testé, quel problème résout, ce à quoi vous devez faire attention.

Je suis un fervent partisan de la deuxième approche - il est gênant pour moi de battre mon travail en micro-morceaux. Je prends une petite tâche et me précipite au hasard autour de la base de code, expérimentant et apportant des modifications dans l'ordre dans lequel il se révèle. Si je pouvais cliquer sur un bouton, et que mon travail serait restructuré en bons commits, je cliquerais dessus. Mais il n'y a pas de bouton, mais je ne veux pas me casser. Dans le même temps, j'ai atteint une certaine habileté à décrire le pool de demandes. Il m'est arrivé de comprendre le code dans Microsoft (via outstaff, cela ne compte pas), et là, j'ai obtenu les meilleures normes pour enregistrer un pool de demandes. Au fil des années, je viens de développer cette pratique. D'habitude, j'ai réussi à convaincre l'équipe d'utiliser une telle approche.

Mais au dernier emploi, je suis devenu devlid - un fervent partisan des commits détaillés. Oh, nous nous sommes disputés pendant longtemps. Ma position subordonnée a joué un rôle, l'habitude de Sovkovsky d'être d'accord avec l'essentiel n'est pas facile à fermer. Je n'étais pas aussi catégorique que d'habitude et j'étais couché sur les deux lames. Empilé, mais pas convaincu.



Si soudain les développeurs s'unissent en un seul gouvernement, établissent des règles et commencent à proclamer certaines approches interdites, une guerre civile commencera le lendemain. Tout cela parce que dans le monde des développeurs, il y a une croyance en l'objectif et mesurable. Dans la vérité indépendante de la perception humaine. Et si tout cela existe, cela signifie que l'un des opposants a manifestement tort objectivement.

Mon premier conflit de travail grave s'est produit assez tôt. J'étais toujours un vert juin, qui pense qu'il est au milieu des pommes, et en effet un développeur très cool et intelligent. Un vrai développeur de mon équipe a lancé PR. Nous avions l'habitude que tous les membres de l'équipe rédigent un code de révision. J'ai ouvert le code et j'ai vu presque immédiatement le problème. Un homme a écrit un test pour une fonction qui prenait un certain nombre. Il l'a donc nourrie à 0, 1000 et au hasard (0, 1000).

À cette époque, je ressentais très vivement que d'autres coéquipiers me considéraient comme un stupide nouveau venu. Et il attendit un moment pour les enduire de sa vision. J'ai eu de la chance - aléatoire dans les tests!

Je ne comprenais pas vraiment la théorie des tests unitaires, mais j'ai lu quelques livres, et je me souviens fermement - le même test unitaire sur la même base de code devrait donner le même résultat. J'ai passé environ une heure à réfléchir au commentaire pour qu'il ne paraisse pas toxique, mais il a été clair que seul le singe, qui avait appris à compter hier, pouvait prendre une telle décision. En fin de compte, bien sûr, il avait l'air extrêmement stupide, comme tout ce que les stagiaires d'hier qui s'imaginaient être des développeurs se retiraient d'eux-mêmes.

Le lendemain, j'ai réalisé que j'avais ouvert un portail vers l'enfer. Il y en avait une centaine de plus sous mon commentaire. Pour le reste de la journée, au lieu d'une équipe de six développeurs, nous étions une équipe de six singes. Nous nous sommes disputés en anglais dans PR même si tout le monde était russe. Lorsque le stock de mots n'était pas suffisant, ils ont appelé. Ils se sont jetés dessus avec des liens, des citations de livres, des études, tournés vers l'individu. Un collègue a répondu à l'un de mes commentaires par une capture d'écran d'un dictionnaire anglais afin de ridiculiser mon anglais. Mais nous ne sommes pas parvenus à un compromis.

La question était compliquée. D'une part, nous ne savions pas du tout de quoi ce paramètre était responsable, notre fonction l'a transmis à l'autre, depuis un réseau interne vers lequel il n'y avait pas de quais. Par conséquent, théoriquement, la fonction pourrait tomber sur n'importe quelle valeur, ce qui signifie que le test pourrait l'attraper, puis nous pourrions anticiper l'erreur sur le prod. D'un autre côté, nous avons déjà eu le problème de construire au hasard des constructions. Pour cette raison, si le projet était en cours de construction local et se bloquait, nous avons stupidement commandé une nouvelle version et n'avons pas regardé les journaux. Après tout, la construction a pris quatre heures, et personne ne regardait la demande d'extraction jusqu'à ce qu'elle passe CI.

De plus, les voitures étaient souvent occupées - il était beaucoup plus pragmatique de commander une construction alors qu'elle était encore commandée que de rechercher un «problème» potentiel (qui s'est presque toujours avéré être un temps mort de vol dans le test d'intégration). Cela signifiait que même si le test aléatoire tombait, nous n'y ferions pas attention.

Tout a été résolu sur le prochain dealik. Nous avons téléphoné à toute l'équipe et pendant une demi-heure, nous avons continué à discuter - en russe. Nous n'avons pas remarqué comment notre directeur du développement américain a rejoint l'appel et avons continué à nous écraser avec des arguments à des tonalités élevées. Jusqu'à ce qu'ils entendent «Hé les gars, ce n'est absolument pas important. Il suffit de le fusionner tel quel. " Je ne sais pas combien de temps il nous a écoutés auparavant, et comme il comprenait de quoi nous parlions, mais nous nous sommes arrêtés brusquement. Ils se figèrent et l'oublièrent. Séparé en paix, mais pas convaincu.



Depuis lors, j'ai acquis de l'expérience afin de comprendre - mais je ne donne pas du tout la merde, les cas aléatoires, les handicaps ou les limites. Ce foutu test unitaire va interférer - nous allons réécrire. Tout vaut mieux que de se disputer toute la journée. Mais si vous imaginez que je suis dans un monde idéal, où il est toujours nécessaire de ne prendre que des décisions plus correctes, je ne sais pas quoi faire. Nous avons gelé un test au hasard, et maintenant je comprends cela comme un choix en faveur de la fiabilité, mais au détriment de la commodité du développement.

L'autre jour, j'ai été confronté à un dilemme similaire. J'ai joué avec le nouveau timecode et écrit une chose qui peut être utilisée comme ça

// LessThan<T>  MoreThan<T> -    ,   . 
// ,        

//      , 
//   ,   100
const consumeNumberLessThan100 = (v: LessThan<100>) => 
    doWork(v);

//     ,   100
const consumeNumberMoreThan100 = (v: MoreThan<100>) => doWork(v);

const sample = (x: number) => {

    //     check  , 
    //   x  100
    //  "<"  ">"  , 
    //     -   
    const lessThan100 = check(x,'<', 100);

    if (lessThan100) {
        //     -  
        //       
        //    ,  lessThan100  - LessThan<100>
        //    
        consumeNumberLessThan100(lessThan100); 

        //   -  ,   , 
        //  ,   > 100.
        consumeNumberMoreThan100(lessThan100);
    }

    const moreThan100 = check(x, '>', 100);

    if (moreThan100) {
        consumeNumberMoreThan100(moreThan100); // 
        consumeNumberLessThan100(moreThan100); // 
    }

    consumeNumberLessThan100(x); // 
    consumeNumberMoreThan100(x); // 
}

J'ai pensé, bon sang, c'est très cool - vous pouvez donc attraper un grand nombre d'erreurs à un stade antérieur. La conception de mes outils de restriction de valeur est terrible, mais pour l'instant ce n'est qu'un concept. À l'avenir, vous pouvez facilement l'étendre, créer un DSL puissant et formuler des conditions vraiment complexes pour la correspondance des paramètres garantis au stade de la compilation. J'ai compris comment cela peut augmenter la fiabilité de n'importe quelle base de code, amélioré et envoyé un extrait à divers développeurs familiers.

Les avis étaient de nouveau partagés, et non dans ma direction. La re-complication, la suringénierie, n'est pas prise en charge, tout le monde bloquera votre garde à l'aide d'un casting eni. Illisible. Bon car une expérience est mauvaise dans le projet actuel. Des exemples d'utilisation sont tirés du doigt. Mettez-vous au travail, Phil.

Les partisans de l'approche ont dit, oui, si fiables. Le plus tôt vous attrapez une erreur, mieux c'est. De plus, si vous écrivez une fonction qui fonctionne avec un nombre limité, vous devez toujours écrire une vérification, mais cela ne fonctionnera qu'en runtime et augmentera la quantité de code dans le corps de la fonction.

Maintenant, je suis un peu plus intelligent qu'avant et j'ai appris à entendre les arguments. Je m'imaginais écrire une fonction protégée par mon type dans un vrai projet. Comme tous ceux qui l'utilisent, me demandent ce que c'est. Comment, après avoir tâtonné la puce, ils commencent à recouvrir la base de code avec un DSL personnalisé et pourri. Comme nous vérifions trois cents fois les valeurs qui, en fait, ne dépasseront jamais les valeurs autorisées. L'approche est vraiment terrible à utiliser, certains problèmes peuvent être résolus ou lissés, mais par exemple, un tel cas

consumeNumberLessThan100(90);

Ne lissez en aucune façon. Je vais devoir prouver au compilateur que 90 est inférieur à 100. Je fournirai n'importe quelle activité, et il se révélera

consumeNumberLessThan100(assert(90, '<', 100)); 

Ça n'a pas l'air très cool. Tous les arguments contre sont à portée de main, mais ils ne contredisent pas les arguments pour. Il en résulte un dilemme: facilité de développement ou fiabilité. Ici, nous tombons dans le piège, nous commençons à penser que nous devons calculer le type de commodité et le type de fiabilité. Mais la commodité et la fiabilité du développement sont des choses très, très complexes. Ils se composent de milliers de paramètres.

Par exemple, la commodité est lorsque l'IDE compile le code pour vous sur une paire de caractères entrés, lorsque le code est facile à lire, lorsque vous pouvez modifier la fonctionnalité de la méthode sans regarder le document. Lorsque le compilateur n'est pas chargé avec une analyse statique, la construction est rapide, l'éditeur de texte rend instantanément les caractères. Mais lorsque le compilateur détecte et met en évidence l'erreur pour vous, c'est aussi une commodité. Et c'est aussi la fiabilité. Qui à son tour est assemblé à partir d'un grand nombre de choses complètement différentes.

Vous devez vous asseoir et calculer combien de temps le projet durera, dans quelle direction il ira, combien de fois dans l'histoire de l'humanité quelqu'un appellera l'une ou l'autre méthode de votre base de code, quels développeurs travailleront ici. Il s'agit d'une liste interminable de questions pour la bonne moitié desquelles il est impossible de calculer la bonne réponse. Juste devine.



Une fois, un ami m'a demandé de préparer des questions techniques pour une entrevue avec Andrei Breslav. Je suis allé au quai de Kotlin pour trouver des points controversés dans la conception. Ils sont là, comme ailleurs, dans l'obscurité. Mais ce qui m'a le plus intéressé, c'est l'approche du traitement des exceptions. Un gestionnaire d'exceptions dans Kotlin est une expression, une approche complètement fonctionnelle et fiable. C'est juste pour gérer les erreurs n'est pas nécessaire. Ce qui ramène toute fiabilité à zéro. Et cela est intéressant car en plein dans le dock, les développeurs n'étaient pas trop paresseux pour expliquer leur choix: "il y a des études selon lesquelles la gestion obligatoire des erreurs réduit considérablement la productivité des développeurs avec une légère diminution des erreurs."

Je suis fou, comment pouvez-vous écrire du code si vous ne savez pas quoi faire quand il ne fonctionne pas correctement!? Si vous ne savez pas comment gérer l'exception, alors ne la gérez pas - pas une solution au problème, mais des étagères. À un moment donné, le code tombera et un problème qui existe toujours causera des dommages qui auraient pu être anticipés.

Mais un argument logique contre n'est pas nécessaire, vous pouvez faire uniquement des statistiques. Pour les développeurs de kotlin, la recherche brise la logique car ils ont une philosophie. Leur philosophie est le pragmatisme. Fer, pragmatisme incassable, systématiquement intégré à toutes les fonctionnalités de ce langage de programmation. Les idéalistes qui ont vu les Haskels / Idris et les govnokoders qui écrivent le golang font exactement la même chose. La philosophie du compromis raisonnable règne dans la base de code F #. Et il n'y a aucun sentiment que l'un d'eux a raison, et les autres sont des imbéciles.

Tous ces gens sont beaucoup plus intelligents et plus expérimentés que des gens comme moi, et ils semblent avoir compris depuis longtemps que vous développez une philosophie pour vous-même, puis vous la suivez simplement. Parce que la principale caractéristique de toute philosophie est de résoudre les dilemmes.

Et donc la philosophie est apparue dans tout en informatique, et la philosophie est l'exact opposé de l'idée d'une seule et vraie objectivité, parce que la philosophie propose de choisir la vérité subjective pour vous-même.

Chacun de nous a sa propre philosophie - elle n'est pas décrite en un mot, c'est un ensemble complexe de modèles pour prendre des décisions. Et nous les modifions ou les développons souvent. En pratique, il s'avère que vous avez un projet avec votre propre philosophie, qui est écrit dans un langage de programmation avec votre propre philosophie, en utilisant des cadres et des outils, chacun ayant sa propre philosophie. Et les développeurs écrivent ce projet, chacun avec sa propre philosophie. Et chaque fois que vous devez prendre une sorte de décision, seule une combinaison de circonstances affecte celle qui sera prise. Pas de gestion de la complexité, pas d'expérience, pas d'approche, pas de connaissance, mais juste un accident.

Et tous ces projets fonctionnent. La part du lion de toutes les tâches que les développeurs résolvent est l'élimination des conséquences des erreurs des autres développeurs, mais les projets fonctionnent et résolvent les problèmes des gens. Les gens intelligents proposent des pratiques et des modèles architecturaux. Langages de programmation avec contrôle de type et contrats puissants - tout, si seulement les développeurs se trompaient moins. Et chaque jour, j'ouvre le Edge Board au travail, et je vois qu'il y a plus de bugs que de tâches. Où est chaque bug, c'est un autre, la gestion de la complexité, merde développeur.

La philosophie de développement est simplement le choix de la façon dont vous mettez la main sur la finale. Mais s'il n'y a pas de philosophie, mais seulement une logique objective pure, alors tout argument se résumera au problème du créateur omnipotent et de la pierre insupportable.



Je suis en développement depuis longtemps, et j'ai appris à faire ce qu'ils disent, même lorsque je suis fondamentalement en désaccord, et j'ai commencé à écrire des commits super détaillés. Mon devlid est un vrai vampire. Cela ne nécessite pas seulement une description - il veut que j'écrive ce que fait chaque fichier, pourquoi il le fait, comment il le fait. Quel problème commet commit?

J'ai ajouté huit commits extra-détaillés, la même description détaillée du pool de requêtes - et j'ai bien aimé les kapets. Depuis lors, nous n'avons presque pas travaillé sur ce projet particulier, mais de temps en temps j'y vais pour admirer ces commits. Sérieusement, vraiment, vraiment cool. Et dans tous les autres projets, à l'exception de mes projets personnels, j'applique maintenant cette approche.

Il m'a été très difficile de reconstruire le workflow. Un mois et demi s'est écoulé et il m'est encore difficile d'écrire du code comme celui-ci. Mais cela en vaut la peine.

Ou pas. Honnêtement, je ne sais pas. Et je ne sais pas si ça en vaut vraiment la peine, est-ce que ça fait de moi un idiot à deux mois. Une dizaine de personnes se promènent quelque part dans le monde que j'ai appris à ne pas commettre. Sont-ils des idiots? Je ne pense pas.



Mon podcast

All Articles