Il s'agit d'une collection cynique et clinique de ce que j'ai appris au cours des 30 dernières années dans le développement de logiciels. Je le répète, certaines choses sont très cyniques et le reste est le résultat de longues observations à différents lieux de travail.
Développement logiciel
Spécifications d'abord, puis code
Si vous ne savez pas exactement ce que vous essayez de résoudre, vous ne savez pas quel code écrire.
Décrivez d'abord le fonctionnement de votre application avant de commencer la programmation.
«Sans exigences ni projet, la programmation est l'art d'ajouter des bogues à un fichier texte vide.» - Louis SraigleyParfois, même une «brève présentation» suffit - pas plus de deux paragraphes décrivant ce que fait votre demande.
Il y a eu des moments où, en raison d'étapes non écrites, j'ai passé plus de temps à regarder le code et à me demander quoi faire ensuite. C'est un bon signe qu'il est temps de s'arrêter et de discuter de la situation avec des collègues. Ou peut-être repenser la décision.
Décrire les étapes sous forme de commentaires
Si vous ne savez pas par où commencer, décrivez le flux de données de niveau supérieur dans votre application, simplement dans votre langue maternelle. Et puis remplissez le code vide entre les commentaires.
Ou encore mieux: lisez chaque commentaire en tant que fonction, puis écrivez une fonction qui fait exactement cela.
Gherkin vous aide à réaliser vos attentes
Gherkin est un format de description de test dont le principe se lit comme suit: «Étant donné que le système est dans un certain état, si quelque chose se produit, cela est attendu.» Si vous n'utilisez pas d'outils de test qui comprennent Gherkin, cela vous donnera une bonne idée de ce à quoi vous attendre de l'application.
Les tests unitaires sont bons, les tests d'intégration sont encore meilleurs
Dans mon travail actuel, nous testons uniquement des modules et des classes. Par exemple, nous écrivons des tests uniquement pour le niveau de présentation, puis nous écrivons des tests uniquement pour le niveau du contrôleur, etc. Cela nous aide à comprendre si tout est en ordre, mais ne nous permet pas de voir l'ensemble de ce qui se passe - pour cela, les tests d'intégration qui vérifient le comportement de l'ensemble du système sont beaucoup plus utiles.
Les tests améliorent les API
Nous programmons dans le cadre de niveaux: il existe un niveau de stockage qui devrait rendre nos données éternelles; il existe un niveau de traitement qui doit en quelque sorte transformer les données stockées; il existe une couche de présentation qui contient des informations sur la présentation des données, etc.
Comme je l'ai dit, les tests d'intégration sont meilleurs, mais tester les niveaux eux-mêmes vous permet de mieux comprendre à quoi ressemblent leurs API. Ensuite, vous comprendrez mieux la situation avec les appels de quelque chose: l’API est-elle trop compliquée? Dois-je garder autant de données à proximité pour passer un appel?
Faites des tests que vous pouvez exécuter à partir de la ligne de commande
Je veux dire, non pas les lignes de commande elles-mêmes sont importantes pour n'importe quel objet, mais votre connaissance des commandes pour exécuter les tests, votre capacité à automatiser leur exécution, que vous pouvez ensuite appliquer dans l'outil d'intégration continue.
Soyez prêt à envoyer votre code au panier
Beaucoup de ceux qui commencent à développer sur la base de tests (TDD) sont ennuyés lorsque vous leur dites que vous devrez peut-être réécrire une grande partie de leur code, y compris ce que vous avez écrit vous-même.
TDD a été
inventé pour lancer du code: plus vous en apprenez sur un problème, plus vous comprenez que ce que vous écrivez ne le résoudra pas à long terme.
Ne vous en faites pas. Votre code n'est pas un mur: si vous devez toujours le jeter, ce n'est pas un gaspillage. Bien sûr, vous avez perdu du temps à écrire du code, mais maintenant vous comprenez mieux le problème.
Une bonne langue a intégré des tests
Je vous assure: si la bibliothèque de langues standard a un cadre de test - quoique minime - alors dans l'écosystème associé, les tests seront meilleurs que dans une langue qui n'a pas un tel cadre, quels que soient les mérites des cadres de test externes pour ce langage.
Penser à l'avenir, c'est gaspiller votre énergie
Lorsque les développeurs tentent de résoudre un problème, ils essaient parfois de trouver un moyen de résoudre tous les problèmes, y compris ceux qui pourraient survenir à l'avenir.
Je vais vous dire une chose: ces problèmes futurs ne se poseront jamais, et vous devrez accompagner une énorme pile de code qui ne sera pas utilisée dans son intégralité, ou vous devrez tout réécrire en raison du tas de code inutilisé.
Résolvez le problème maintenant. Décidez ensuite ce qui suit. Puis le suivant. Une fois que vous avez remarqué un schéma qui se pose sur la base de ces décisions, vous ne trouverez alors que votre «solution universelle».
La documentation est un futur message d'amour pour vous
Nous savons tous de quel type d'hémorragie il s'agit d'écrire une maudite documentation sur les fonctions, les classes et les modules. Mais comprendre le cours de vos pensées lorsque vous avez écrit telle ou telle fonction peut vous sauver le cul à l'avenir.
La documentation fonctionnelle est son contrat
En commençant à écrire de la documentation, vous créez en fait un contrat (peut-être avec vous-même): "J'affirme que cette fonction fait
cela , et c'est ce qu'elle fait."
Si vous constatez plus tard que votre code n'est pas conforme à la documentation, ce sera un problème de code, pas une documentation.
Si la description de la fonction a «et», alors c'est mauvais
Une fonction ne doit faire qu'une seule chose. Lorsque vous y écrivez de la documentation et que vous voyez que vous avez ajouté un «et», cela signifie que la fonction fait autre chose. Divisez-le en deux fonctions et supprimez le «et».
N'utilisez pas de valeurs booléennes comme paramètres
Lors du développement d'une fonction, vous pourriez être tenté d'ajouter un indicateur. Ne fais pas ça.
Je m'explique avec un exemple: disons que vous avez un système de messagerie et qu'il existe une fonction
getUserMessages
qui renvoie tous les messages à l'utilisateur. Mais il existe une situation dans laquelle vous devez renvoyer soit un bref résumé de chaque message (par exemple, le premier paragraphe), soit l'intégralité du message. Par conséquent, vous ajoutez un paramètre sous la forme d'un indicateur ou d'une valeur booléenne que vous appelez
retrieveFullMessage
.
Encore une fois, ne faites pas cela.
Parce que ceux qui liront votre code verront
getUserMessage(userId, true)
et se demanderont ce que c'est?
Ou vous pouvez renommer la fonction
getUserMessageSummaries
et entrer
getUserMessagesFull
, ou quelque chose de similaire, mais chaque fonction appellera simplement le
getUserMessage
origine avec
true
ou
false
- mais l'interface en dehors de votre classe / module sera claire.
Mais n'ajoutez pas de drapeaux ou de paramètres booléens aux fonctions.
Méfiez-vous des changements d'interface
Dans le paragraphe précédent, j'ai mentionné le changement de nom d'une fonction. Si vous contrôlez la source dans laquelle la fonction est utilisée, ce n'est pas un problème, c'est seulement une question de recherche et de remplacement. Mais si la fonction est fournie par la bibliothèque, vous n'avez pas besoin de changer le nom à votre guise. Cela cassera de nombreuses autres applications que vous ne contrôlez pas et bouleversera de nombreuses personnes.
Vous pouvez créer de nouvelles fonctions et marquer la fonction actuelle comme indésirable dans un document ou au moyen de code. Et après quelques sorties, vous pouvez enfin la tuer.
Solution laide: créez de nouvelles fonctions, marquez l'actuelle comme indésirable et
ajoutez du sleep
au début de la fonction pour forcer ceux qui utilisent l'ancienne fonction à être mis à jour.
Les bonnes langues ont une documentation intégrée
Si le langage utilise sa propre façon de documenter les fonctions, les classes, les modules et tout le reste, et même s'il existe un simple générateur de documentation, alors tout ce qui est mentionné sera bien documenté (pas génial, mais au moins bon).
Et les langues qui n'ont pas de documentation intégrée sont souvent mal documentées.
La langue est plus qu'une simple langue
Vous écrivez dans un langage de programmation et faites «fonctionner» les choses. Mais il n'y a pas que des mots spéciaux: le langage a un système d'assemblage, un système de gestion des dépendances, des outils pour interagir avec des outils, des bibliothèques et des frameworks, il y a une communauté, il y a un moyen d'interagir avec les gens.
Ne sélectionnez pas de langues pour faciliter l'utilisation. N'oubliez pas que vous pouvez trouver la syntaxe simple, mais en choisissant cette langue, vous choisissez également la façon dont les créateurs de la langue communiquent avec sa communauté.
Parfois, il vaut mieux laisser l'application se bloquer que de ne rien faire.
Bien que cela semble étrange, il vaut mieux ne pas ajouter de gestion des erreurs que de les attraper tranquillement et de ne rien faire.
Java a un modèle malheureusement commun:
try { something_that_can_raise_exception() } catch (Exception ex) { System.out.println(ex); }
Rien n'est fait avec une exception ici, seul un message est affiché.
Si vous ne savez pas comment gérer l'erreur, laissez-la se produire, afin que vous puissiez au moins savoir
quand elle s'est produite.
Si vous savez comment traiter, faites-le
Contrairement au paragraphe précédent: si vous savez quand une exception, une erreur ou un résultat apparaît et que vous savez comment le gérer, faites-le. Affichez le message d'erreur, essayez d'enregistrer les données quelque part, supprimez les données entrées par l'utilisateur pour une utilisation ultérieure dans le journal, ne les
traitez que .
Les types parlent de vos données
La mémoire n'est qu'une séquence d'octets. Les octets sont simplement des nombres de 0 à 255. La signification de ces nombres est décrite dans le système de type de langue.
Par exemple, en C, le type de caractère (type char) avec une valeur de 65 sera probablement la lettre «A», et un int avec une valeur de 65 sera le nombre 65.
Gardez cela à l'esprit lorsque vous travaillez avec vos données.
Lors de l'ajout de booléens, beaucoup oublient de vérifier le nombre de valeurs
True
. Récemment, je suis tombé sur cet exemple JavaScript:
console.log(true+true === 2); > true console.log(true === 1); > false
Si vos données ont un schéma, stockez-les en tant que structure
Si les données sont simples, par exemple, seulement deux champs, alors vous pouvez les stocker dans une liste (ou un tuple si votre langue le permet). Mais si les données ont un schéma - un format fixe - alors utilisez toujours une structure ou une classe pour les stocker.
Reconnaissez et éloignez-vous du culte du fret
L'idée du «culte du fret» est que si quelqu'un le faisait, alors nous le pouvons. Le plus souvent, le culte du fret est simplement une «échappatoire facile» au problème: pourquoi devrions-nous réfléchir à la façon de stocker correctement les données utilisateur si X l'a déjà fait?
«Si la grande entreprise stocke les données de cette manière, nous le pouvons.»
"Si la grande entreprise l'utilise, alors c'est bien."
"Le bon outil pour la tâche" est un moyen d'imposer votre opinion
L'expression «le bon outil pour la tâche» devrait signifier qu'il existe un bon et un mauvais outil pour quelque chose. Par exemple, utiliser un langage ou un cadre spécifique au lieu du langage ou du cadre actuel.
Mais chaque fois que j'entends cette expression de quelqu'un, les gens poussent leur langage / cadre préféré de cette façon, au lieu, disons, du langage / cadre correct.
Le «bon outil» est plus évident que vous ne le pensez
Peut-être que maintenant vous participez à un projet dans lequel vous souhaitez traiter du texte. Vous voudrez peut-être dire: «Utilisons Perl parce que tout le monde sait que Perl est très bon pour traiter du texte.»
Ce que vous oubliez: votre équipe est spécialisée en C. Tout le monde connaît C, pas Perl.
Bien sûr, si c'est un petit projet "à genoux", alors c'est possible sur Perl. Et si le projet est important pour l'entreprise, il vaut mieux l'écrire en C.
PS: Votre projet héroïque (plus de détails ci-dessous) peut échouer à cause de cela.
Ne rentre pas dans ce qui est en dehors de ton projet
Parfois, au lieu d'utiliser des outils d'extension appropriés, les gens commencent à changer les bibliothèques et les cadres externes. Par exemple, apportez des modifications directement à WordPress ou Django.
Ainsi, vous pouvez facilement et très rapidement rendre le projet impropre à la maintenance. Dès que la nouvelle version sera publiée, vous devrez synchroniser les modifications avec le projet principal, et bientôt vous constaterez que vous ne pourrez plus appliquer les modifications et laisser l'ancienne version de l'outil externe pleine de failles de sécurité.
Les flux de données battent les modèles
Ceci est mon opinion personnelle. Si vous comprenez comment les données doivent passer par votre code, ce sera mieux pour lui que si vous utilisez un tas de modèles de conception.
Les modèles de conception sont utilisés pour décrire des solutions, pas pour les trouver.
Encore une fois mon opinion personnelle. Selon mes observations, le plus souvent, les modèles de conception sont utilisés pour trouver une solution. Et en conséquence, la solution - et parfois le problème lui-même - est déformée pour s'adapter au modèle.
Tout d'abord, résolvez votre problème. Trouvez une bonne solution, puis recherchez parmi les modèles pour savoir comment s'appelle votre solution.
J'ai vu cela plusieurs fois: nous avons un problème, le modèle est proche de la bonne solution, utilisons le modèle, maintenant nous devons ajouter un tas de tout à la bonne solution, afin qu'elle corresponde au modèle.
Apprenez les bases de la programmation fonctionnelle
Vous n'avez pas besoin d'approfondir les questions «que sont les monades» ou «est-ce un foncteur». Mais rappelez-vous: vous ne devez pas modifier constamment les données; créer de nouveaux éléments avec de nouvelles valeurs (considérer les données comme immuables); dans la mesure du possible, faites des fonctions et des classes qui ne stockent pas d'états internes (fonctions et classes pures).
L'effort cognitif est l'ennemi de la lisibilité.
"
La dissonance cognitive " est une expression voilée "pour comprendre cela, je dois me souvenir simultanément de deux (ou plus) choses différentes." Et plus cette information est indirecte, plus vous devez consacrer d'efforts à la garder dans votre tête.
Par exemple, l'ajout de booléens pour compter les valeurs
True
est une version légère de la dissonance cognitive. Si vous lisez le code et voyez la fonction
sum()
, qui, comme vous le savez, ajoute tous les nombres dans la liste, alors vous vous attendez à voir une liste de nombres; et j'ai rencontré des gens utilisant
sum()
pour compter les
True
valeurs dans une liste de booléens, ce qui est complètement déroutant.
Nombre magique sept plus ou moins deux
Le «
nombre magique » est un article de psychologie qui décrit le nombre d'éléments qu'une personne est capable de conserver simultanément dans la mémoire à court terme.
Si vous avez une fonction qui appelle une fonction qui appelle une fonction qui appelle une fonction qui appelle une fonction qui appelle une fonction, alors c'est juste l'enfer pour le lecteur de votre code.
Pensez-y: je vais obtenir le résultat de cette fonction, le passer à la deuxième fonction, obtenir son résultat, passer la troisième, etc.
De plus, les psychologues parlent aujourd'hui plus souvent du nombre magique QUATRE, plutôt que de sept.
Pensez à la catégorie de «composition des fonctions» (par exemple, «j'appellerai cette fonction, puis à celle-là, puis là ...»), et non à la catégorie «appel de fonctions» (par exemple, «cette fonction appellera cela, elle appellera cela. .. ").
Les coupes sont bonnes, mais seulement à court terme
De nombreux langages, bibliothèques et frameworks proposent des méthodes de raccourci pour réduire le nombre de caractères que vous saisissez.
Mais plus tard, cela vous revient, et vous serez obligé de supprimer les coupures et d'écrire tout dans son intégralité.
Alors, découvrez d'abord ce que fait une abréviation particulière avant de l'utiliser.
Vous n'avez pas besoin d'écrire le tout au début, puis de le changer en abréviation: faites ce que les abréviations font pour vous, et au moins vous comprendrez ce qui pourrait mal tourner, ou comment remplacer quelque chose par une version non abrégée.
Résistez à la tentation de la "facilité"
Bien sûr, l'IDE vous aidera à terminer automatiquement un tas de tout et facilitera la construction d'un projet, mais comprenez-vous même ce qui se passe là-bas?
Savez-vous comment fonctionne votre système de build? Si vous devez l'exécuter sans IDE, pouvez-vous le faire?
Vous souvenez-vous des noms de fonction sans complétion automatique? Est-il possible de casser quelque chose ou de le renommer pour qu'il soit plus facile à comprendre?
Intéressez-vous à ce qui se passe sous le capot.
TOUJOURS utiliser les fuseaux horaires dans les dates
Lorsque vous travaillez avec des dates, ajoutez
toujours des fuseaux horaires. Vous aurez
toujours des problèmes avec les fuseaux horaires qui ne correspondent pas sur les ordinateurs et les serveurs, et vous perdrez beaucoup de temps pour le débogage, en essayant de comprendre pourquoi l'interface affiche le mauvais moment.
TOUJOURS utiliser UTF-8
Vous aurez les mêmes problèmes avec les encodages qu'avec les dates. Par conséquent, convertissez toujours les valeurs de chaîne en UTF-8, stockez-les dans des bases de données en UTF-8 et revenez de vos API à UTF-8.
Vous pouvez convertir n'importe quel autre encodage, mais UTF-8 a vaincu la guerre d'encodage, donc la façon la plus simple de s'y tenir.
Commencez stupide
Une des façons de s'éloigner de l'IDE est de "démarrer de manière stupide": prenez simplement le compilateur, N'IMPORTE QUEL éditeur avec la mise en évidence du code et - programmez, construisez, exécutez.
Oui, ce n'est pas facile. Mais quand plus tard vous utiliserez une sorte d'IDE, vous ne penserez qu'aux boutons "Oui, ça lance ça." C'est exactement ce que font les IDE.
Les journaux sont pour les événements, pas pour l'interface utilisateur.
Pendant longtemps, j'ai utilisé des journaux pour montrer aux utilisateurs ce qui se passe avec l'application. Eh bien, vous savez, car il est beaucoup plus facile d'utiliser une chose que deux.
Pour informer les utilisateurs des événements, utilisez le formulaire de sortie standard. Pour les rapports d'erreurs, messages d'erreur standard. Et utilisez les journaux uniquement pour stocker des données que vous pourrez facilement traiter ultérieurement.
Les journaux ne sont pas une interface utilisateur, mais une entité que vous devez analyser pour récupérer des informations au bon moment. Les journaux ne doivent pas être lisibles par l'homme.
Débogueurs surévalués
J'ai entendu beaucoup de plaintes selon lesquelles les éditeurs de code sans débogueur sont terribles, précisément parce qu'ils n'ont pas de débogueur.
Mais lorsque votre code est en fonctionnement, vous
ne pouvez pas exécuter votre débogueur préféré. Enfer, vous ne pouvez même pas exécuter votre IDE préféré. Mais la journalisation ... ça marche partout. Il se peut que vous ne disposiez pas des informations souhaitées au moment de la chute (par exemple, en raison de différents niveaux de journalisation), mais vous
pouvez activer la journalisation pour en connaître la raison ultérieurement.
Je ne parle pas du fait que les débogueurs eux-mêmes sont mauvais, ils ne fournissent tout simplement pas l'aide que beaucoup attendent d'eux.
Utilisez toujours un système de gestion des versions
«C'est juste ma stupide application avec laquelle je veux apprendre quelque chose» - cela ne justifie pas l'absence d'un système de versioning.
Si vous utilisez un tel système depuis le tout début, il sera plus facile de revenir en arrière en cas d'erreur.
Un changement par commit
J'ai rencontré des gens qui écrivent les messages suivants dans les commits: «Corrige le problème 1, 2 et 3». À moins que tous ces problèmes ne se chevauchent - dont deux devraient déjà être fermés - il devrait y avoir trois commits au lieu d'un.
Adhérez au principe «un changement par commit». Et par changement, je veux dire un changement dans un fichier. Si vous devez modifier trois fichiers, validez ces fichiers ensemble. Posez-vous la question: «si j'annule ce changement, qu'est-ce qui devrait disparaître?»
"Git add -p" vous aidera avec beaucoup de changements
Cela ne s'applique qu'à Git. Il vous permet de fusionner partiellement des fichiers en utilisant le paramètre "-p", de sorte que vous ne pouvez sélectionner que les modifications liées les unes aux autres, en laissant les autres pour le nouveau commit.
Structurer les projets par données ou type, pas par fonctionnalité
La plupart des projets utilisent la structure suivante:
. +-- IncomingModels | +-- DataTypeInterface | +-- DataType1 | +-- DataType2 | +-- DataType3 +-- Filters | +-- FilterInterface | +-- FilterValidDataType2 +-- Processors | +-- ProcessorInterface | +-- ConvertDataType1ToDto1 | +-- ConvertDataType2ToDto2 +-- OutgoingModels +-- DtoInterface +-- Dto1 +-- Dto2
C'est-à-dire que les données sont structurées par fonctionnalité (tous les modèles d'entrée sont dans un répertoire ou package, tous les filtres sont dans un autre répertoire ou package, etc.).
Cela fonctionne très bien. Mais lorsque vous structurez en fonction des données, il est beaucoup plus facile de diviser le projet en plus petits, car à un moment donné, vous devrez peut-être presque tout faire de la même manière que maintenant, avec seulement des différences mineures.
. +-- Base | +-- IncomingModels | | +-- DataTypeInterface | +-- Filters | | +-- FilterInterface | +-- Processors | | +-- ProcessorInterface | +-- OutgoingModels | +-- DtoInterface +-- Data1 | +-- IncomingModels | | +-- DataType1 | +-- Processors | | +-- ConvertDataType1ToDto1 | +-- OutgoingModels | +-- Dto1 ...
Vous pouvez maintenant créer un module qui
ne fonctionne qu'avec Data1, un autre module qui ne fonctionne qu'avec Data2, etc. Et puis vous pouvez les séparer en modules isolés.
Et lorsque vous devez créer un autre projet, contenant également Data1 et travaillant avec Data3, vous pouvez réutiliser la plupart du code dans le module Data1.
Créer des bibliothèques
J'ai souvent vu comment les développeurs créent des méga-référentiels avec différents projets, ou gardent différentes branches, non pas pour qu'ils soient un environnement temporaire pour rejoindre plus tard la partie principale, mais simplement pour diviser le projet en plus petites parties (parler de la division en modules, imaginez qu'au lieu de construire un nouveau projet qui réutilise le type Data1, j'utilise une branche avec une fonction principale complètement différente et le type Data3).
Pourquoi ne pas allouer des pièces fréquemment utilisées à des bibliothèques pouvant être connectées dans différents projets?
Le plus souvent, la raison en est que les gens ne savent pas comment créer des bibliothèques, ou sont inquiets de savoir comment «publier» ces bibliothèques dans des sources de dépendance sans les révéler (il n'est donc pas préférable de comprendre comment votre outil de gestion de projet obtient des dépendances afin que vous puissiez créer votre propre référentiel de dépendances?).
Apprenez à surveiller
Dans une vie antérieure, j'ai ajouté beaucoup de métriques pour comprendre comment le système se comporte: à quelle vitesse il est arrivé, à quelle vitesse il est allé, combien il y avait entre l'entrée et la sortie, combien de tâches ont été traitées ...
Cela donne vraiment une bonne idée du comportement du système. La vitesse diminue-t-elle? Pour comprendre, je peux vérifier quelles données entrent dans le système. La réduction de vitesse est-elle normale à un moment donné?
Le fait est que sans surveillance supplémentaire, il est plutôt étrange d’essayer de découvrir à quel point le système est «sain». Un bilan de santé de type "Répond-il aux demandes" ne convient plus.
L'ajout précoce de la surveillance vous aidera à comprendre le comportement du système.
Utiliser des fichiers de configuration
Imaginez: vous avez écrit une fonction dont vous avez besoin de transmettre une valeur pour qu'elle démarre le traitement (par exemple, l'ID de compte sur Twitter). Mais alors vous devez le faire avec deux valeurs, et vous appelez simplement la fonction à nouveau avec une valeur différente.
Il est préférable d'utiliser des fichiers de configuration et d'exécuter simplement l'application deux fois, avec deux configurations différentes.
Les options de ligne de commande sont étranges, mais elles sont utiles
Si vous transférez quelque chose dans des fichiers de configuration, vous pouvez faciliter la vie de vos utilisateurs et ajouter la possibilité de sélectionner et d'ouvrir le fichier.
Aujourd'hui, pour chaque langue, il existe des bibliothèques qui fonctionnent avec des options pour la ligne de commande. Ils vous aideront à créer un bon utilitaire en fournissant une interface utilisateur standard pour tout.
Pas seulement des compositions fonctionnelles, mais des compositions d'application
Unix utilise ce concept: "des applications qui font une chose et le font bien".
J'ai dit que vous pouvez utiliser une application avec deux fichiers de configuration. Et si vous avez besoin des résultats des deux applications? Ensuite, vous pouvez écrire une application qui lit les résultats de la seconde et combine tout en un résultat commun.
Même lorsque vous utilisez la composition d'application, commencez stupide
La composition des applications peut évoluer en microservices (ce qui est bien), mais elles nécessitent une compréhension de la façon dont les applications "communiquent" entre elles sur le réseau (protocoles et similaires).
Pas besoin de partir de là. Les applications peuvent écrire et lire à partir de fichiers, ce qui est beaucoup plus facile.
Vous penserez à l'interaction à distance plus tard lorsque vous comprendrez le réseau.Laisser des optimisations pour les compilateurs
, . «, », , « , ».
, . , .
,
, , . , . . . , .
, , . Lisp, . , Python
yield
, , , . , , , , .
, , . , « », « » ..
, .
,
, .
, , «»: , , , . , , . , , , .
, , . , .
, . (« ?»), .
… Google
, . , Google , . , , Google , .
C/C++ — K&R
. :)
Python — PEP8
PEP8. , .
, ?
sleep()
.
? ?
, .
sleepForSecs
sleepForMs
, ,
sleep
.
, .
«Zen of Python», .
,
, . , - . - , , , .
« , » — .: , — . , .
, Java , Rust. , Spring , ++.
, — , «» .
, .
—
, , - .
— , — .
« , »
« » « ». , , , , .
, .
,
, , , , .
.
( «»), , , . , AWS SQS ( ), , , RabbitMQ.
- , , , .
Personnel
,
, . , . , .
( , ). , , , .
,
- , , . , ,
, , .
, . , , , « » « , ».
, .
«». , . , . , , . , .
: «, , , , ». , .
.
. - . «» «».
, , , . , .
, ,
. , , - , .
Ne fais pas ça.
- ,
.
- , . , .
, . .
- ,
: - , . , .
«, , » — , .
, , . . , - . . .
, , . , , , - . , , .
,
« ».
- , , , . : « , , ».
.
, , , . .
, .
«»
«» — . , - « », - .
, , , . , , , .
.
, , «»
. - : «, , ?»
, . , , (, , ).
, —
, -, , , , ( ).
… , - , , «
!».
:
«» , , , , . , , .
, /, .
, .
- .
« » « »
: - , , , .
« » — , .
.
,
, , - , .
- .
, .
, , .
, , , .
… .
IT
.
, , 15 , 3-4 .
.
.
, , , - , , , , , , .
. , , URL, .
Trello — ,
« , », .
,
, « , », « , ».
. . , - .
, .
.
, , .
…
, . , « ». - « », , .
. .
Github «, » . , - .
.
: Python, , Java Python, .
«, »
, , , «, ».
- , , - . , .