Chapitre 7

Notions de base du développement

Maîtriser les conventions de code, la configuration des outils et les bonnes pratiques pour différents langages, adopter des habitudes de développement professionnelles et améliorer la qualité du code ainsi que l’efficacité de la collaboration en équipe.

Apprendre les bases du développement avec Sequential Thinking

Les bases du développement impliquent de nombreux aspects, en utilisantMéthodes de pensée structuréePeut vous aider à maîtriser systématiquement :

1
Conventions de code
Conventions de nommage, de formatage et de commentaires selon les différents langages
2
Configuration des outils
Configuration pratique d’ESLint, Prettier et des outils de formatage
3
Bonnes pratiques
Pratiques pour la gestion des erreurs, les journaux, les performances, la sécurité, etc.
4
Amélioration continue
Revue de code, indicateurs de qualité, gestion de la dette technique

Conventions de code

Une convention de code unifiée rend le code plus lisible et plus facile à maintenir, et constitue la base de la collaboration en équipe. Chaque langage ayant ses propres conventions, nous les présentons ci-dessous par langage.

Conventions de nommage

Variables/fonctions
camelCase
getUserName, calculateTotal
Classe/Composant
PascalCase
UserProfile, LoginForm
Constante
UPPER_SNAKE_CASE
MAX_RETRY_COUNT, API_BASE_URL
Fichier
kebab-case
user-service.ts, login-form.tsx

Configuration ESLint

Recommandé Airbnb ou TypeScript ESLint Configuration.

.eslintrc.json(Airbnb + TypeScript):
{
  "extends": [
    "airbnb-base",
    "airbnb-typescript/base",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "./tsconfig.json"
  },
  "rules": {
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/explicit-function-return-type": "warn",
    "import/prefer-default-export": "off",
    "max-len": ["error", { "code": 100 }]
  }
}

Configuration de Prettier

.prettierrc:
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "arrowParens": "always"
}

Mode strict TypeScript

tsconfig.json (mode strict) :
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  }
}

Conventions React

  • • Utiliser des composants fonctionnels et des Hooks, en évitant les composants de classe
  • • Les props sont définies à l’aide d’interfaces TypeScript
  • • Les noms de composants utilisent PascalCase
  • • Utilisez React.memo pour optimiser les performances (si nécessaire)
  • • Les hooks personnalisés commencent par `use`

Référence rapide pour d'autres langues

Rust
  • • rustfmt (formatage)
  • • clippy (vérification du code)
  • • Convention de nommage snake_case
C#
  • • dotnet format
  • • EditorConfig
  • • Nomination en PascalCase
Swift/Kotlin/Dart
  • • Swift: SwiftLint
  • • Kotlin: ktlint
  • • Dart: dart format

Contrôle de version

Git est l’outil standard du développement moderne. Maîtriser les workflows Git, les stratégies de branches et les processus de revue de code est la base de la collaboration en équipe.

Stratégie de branches

Git Flow
• main : environnement de production
• develop : branche de développement
• feature/* : branche de fonctionnalité
• release/* : branches de publication
• hotfix/* : correctif rapide
GitHub Flow
• main : branche principale
• feature/* : branche de fonctionnalité
• Fusionner via une PR
• Adapté au déploiement continu
GitLab Flow
• main : branche principale
• Branches d’environnement (staging, production)
• Principe de priorité à l’amont

Convention des messages de commit (Conventional Commits)

Format : <type>(<scope>): <subject>
feat(auth): ajouter la fonctionnalité de connexion utilisateur
fix(api): Corriger le problème de performance des requêtes de données
docs(readme): Mettre à jour les instructions d’installation
refactor(utils) : refactoriser la fonction de formatage des dates
feat
Nouvelle fonctionnalité
fix
Corriger des bugs
docs
Mise à jour du document
style
Format du code
refactor
Refactorisation
test
Test
chore
Build/Outils
perf
Optimisation des performances

Configuration des Git Hooks

pre-commit Hook
# Exécuter les vérifications lint et de formatage avant la soumission
npm run lint
npm run format:check
commit-msg Hook
# Vérifier le format du message de commit
npx commitlint --edit $1

💡 Utiliser husky(Node.js) ou pre-commit(Python) Gérer les Git Hooks

Processus de revue de code

1Créer une branche de fonctionnalité, terminer le développement et commettre le code
2Créer une Pull Request et remplir la description ainsi que la checklist du PR
3Les relecteurs de code examinent le code (fonctionnalité, performance, sécurité, maintenabilité)
4Modifier le code en fonction des retours, puis le soumettre à nouveau
5Fusionner dans la branche principale après approbation de la revue

Gestion des dépendances

Gérer correctement les dépendances du projet afin d’assurer la maintenabilité et la sécurité du projet. Les langages ont chacun des méthodes de gestion des dépendances différentes.

Versionnage sémantique (SemVer)

Version majeure (MAJOR)
Modifications d’API incompatibles
2.0.0
Numéro de version mineure (MINOR)
Ajouts de fonctionnalités rétrocompatibles
1.2.0
Numéro de révision (PATCH)
Corrections de problèmes de rétrocompatibilité
1.2.3
Plage de versions: ^1.2.3 (autorise 1.x.x, pas 2.0.0), ~1.2.3 (autorise 1.2.x, pas 1.3.0)

Gestion des fichiers verrouillés

Node.js
  • • package-lock.json(npm)
  • • yarn.lock(yarn)
  • • pnpm-lock.yaml(pnpm)
  • • Valider dans le contrôle de version pour garantir la cohérence
Python
  • • requirements.txt(pip)
  • • poetry.lock(Poetry)
  • • Pipfile.lock(Pipenv)
  • • Utiliser des environnements virtuels pour isoler les dépendances

Audit de sécurité des dépendances

Node.js
npm audit
npm audit fix
yarn audit
pnpm audit
Python
pip-audit
safety check
bandit (vérifications de sécurité du code)

💡 Utiliser Dependabot ou Renovate Mettre à jour automatiquement les dépendances et les correctifs de sécurité

Stratégie de mise à jour des dépendances

  • Mettre à jour régulièrement: Vérifier les dépendances obsolètes une fois par mois
  • La sécurité avant tout: Prioriser la mise à jour des dépendances présentant des vulnérabilités de sécurité
  • Piloté par les tests: exécuter la suite de tests complète après les mises à jour
  • Mise à jour progressive: Mettre à jour une dépendance majeure à la fois pour éviter des changements à grande échelle
  • Enregistrement documentaire : consignez les mises à jour majeures des dépendances et les étapes de migration

Directives de gestion des erreurs

Une bonne gestion des erreurs rend les programmes plus robustes et améliore l’expérience utilisateur. Les différents langages ont des schémas de gestion des erreurs différents.

Classification des types d’erreurs

Erreur métier
  • • Erreurs de saisie utilisateur
  • • Violations des règles métier
  • • Renvoyer des messages d’erreur conviviaux
Erreur système
  • • Échec de la connexion à la base de données
  • • Erreur du système de fichiers
  • • Enregistrer des journaux détaillés
Erreur réseau
  • • Échec de l'appel API
  • • Erreur de délai d’attente
  • • Implémenter un mécanisme de nouvelle tentative

Modes de gestion des erreurs

TypeScript/JavaScript/Python/Java:
try {
  const result = await riskyOperation();
  return result;
} catch (error) {
  logger.error('Échec de l’opération', { error });
  throw new BusinessError('Message d’erreur convivial pour l’utilisateur');
}

Bonnes pratiques de gestion des erreurs

  • Clarifier le type d’erreur: définir des types d’erreur et des codes d’erreur clairs
  • Enregistrer les journaux d’erreurs : Enregistrer les informations d’erreur complètes et le contexte
  • Invites conviviales: afficher des messages d’erreur convivials aux utilisateurs, en masquant les détails techniques
  • Récupération des erreurs: fournit des mécanismes de récupération tels que les nouvelles tentatives et les solutions de repli
  • Frontière d’erreur : utiliser des error boundaries (React) ou un middleware (Express) pour gérer les erreurs de manière centralisée

Normes de journalisation

Une bonne journalisation est la base du débogage et de la supervision. Les journaux structurés facilitent l’analyse et le traitement des logs.

Niveau de journalisation

DEBUG
Informations de débogage détaillées
Débogage de développement
INFO
Informations générales
Fonctionnement normal
WARN
message d’avertissement
Problèmes potentiels
ERROR
Message d’erreur
Erreur mais récupérable
FATAL
erreur fatale
Le système ne peut pas continuer

Journalisation structurée (format JSON)

Exemple :
{
  "timestamp": "2025-01-27T10:30:00Z",
  "level": "ERROR",
  "message": "Échec de la connexion utilisateur",
  "context": {
    "userId": "12345",
    "ip": "192.168.1.1",
    "userAgent": "Mozilla/5.0..."
  },
  "error": {
    "type": "AuthenticationError",
    "message": "Mot de passe incorrect",
    "stack": "..."
  },
  "requestId": "req-abc123"
}

Contexte des journaux

Champ obligatoire
  • • timestamp : horodatage
  • • level : niveau de journalisation
  • • message : message de journal
  • • requestId : ID de requête (suivi)
Champ facultatif
  • • userId : ID utilisateur
  • • operation : type d’opération
  • • duration : durée de l’opération
  • • metadata : métadonnées supplémentaires

Masquage des informations sensibles

  • Mot de passe: ne consignez jamais les mots de passe, utilisez *** Alternative
  • Token: Enregistrer uniquement les premiers et derniers caractères du jeton
  • Numéro d’identification: traitement d’anonymisation, seuls certains chiffres sont affichés
  • Numéro de carte bancaire: Afficher uniquement les 4 derniers chiffres
  • E-mail: un masquage partiel peut être envisagé (par exemple : u***@example.com)

Optimisation des performances

L’optimisation des performances est un processus continu. Il existe des possibilités d’optimisation du niveau du code jusqu’au niveau de l’architecture.

Optimisation des performances du code

Optimisation des algorithmes
  • • Choisir la structure de données appropriée (HashMap vs List)
  • • Évitez les boucles imbriquées ; utilisez des index ou une Map
  • • Utiliser le cache pour éviter les calculs répétés
  • • Analyse de la complexité temporelle (O(n) vs O(n²))
Optimisation du front-end
  • • Découpage du code et chargement paresseux
  • • Optimisation des images (WebP, chargement différé)
  • • Utilisez React.memo pour éviter les re-rendus inutiles
  • • Défilement virtuel (longues listes)

Optimisation des requêtes de base de données

Optimisation des index
  • • Ajouter des index aux champs fréquemment interrogés
  • • Éviter l’indexation excessive (impacte les performances d’écriture)
  • • Utiliser des index composites pour optimiser les requêtes sur plusieurs champs
  • • Analyser régulièrement les plans de requête (EXPLAIN)
Optimisation des requêtes
  • • Évitez SELECT *, interrogez uniquement les champs nécessaires
  • • Utiliser la pagination pour éviter de charger une grande quantité de données en une seule fois
  • • Utilisez JOIN au lieu de plusieurs requêtes
  • • Éviter les problèmes de requêtes N+1

Stratégie de cache

Cache mémoire
  • • Cache local (Map, cache LRU)
  • • Adapté aux données chaudes
  • • Faire attention aux limites de mémoire
Redis
  • • Cache distribué
  • • Définir une date d’expiration
  • • Protection contre la pénétration du cache / l'effondrement / l'avalanche
CDN
  • • Accélération des ressources statiques
  • • Fichiers images, CSS, JS
  • • Mise en cache des nœuds en périphérie

Surveillance des performances

  • Outils APM:New Relic, Datadog, Sentry (surveillance des performances)
  • Analyse des performances:Chrome DevTools、Python cProfile、Go pprof
  • Surveillance des métriques: temps de réponse, débit, taux d’erreur, utilisation des ressources
  • Mécanisme d'alerte: Définissez des seuils de performance et déclenchez automatiquement une alerte lorsqu’ils sont dépassés

Bonnes pratiques de sécurité

La sécurité n’est pas optionnelle, elle est obligatoire. Du niveau du code jusqu’au niveau du déploiement, la sécurité doit être prise en compte à chaque étape.

Validation et nettoyage des entrées

Validation front-end
  • • Valider les saisies de formulaire à l’aide de bibliothèques telles que Zod et Yup
  • • La validation côté client améliore l’expérience utilisateur
  • • Mais ne vous fiez jamais uniquement à la validation côté frontend
Validation du backend
  • • Toutes les entrées doivent être validées
  • • Utiliser une liste blanche plutôt qu’une liste noire
  • • Nettoyer et échapper les entrées utilisateur

Protection contre les attaques courantes

Injection SQL
  • • Utiliser des requêtes paramétrées (Prepared Statements)
  • • Utiliser ORM (Prisma, TypeORM)
  • • Ne concaténez jamais des chaînes SQL
XSS (cross-site scripting)
  • • Échappement de la sortie (échappement automatique de React)
  • • Utiliser Content Security Policy (CSP)
  • • Éviter d’utiliser dangerouslySetInnerHTML
CSRF (Cross-Site Request Forgery)
  • • Utiliser un jeton CSRF
  • • Attribut de cookie SameSite
  • • Valider l’en-tête Referer
Chiffrement des données sensibles
  • • Les mots de passe sont hachés avec bcrypt et Argon2
  • • Le transport utilise HTTPS (TLS)
  • • Chiffrer les données sensibles au repos

Gestion des clés

Variables d’environnement
  • • Utiliser un fichier .env (ne pas le commit dans Git)
  • • Utiliser .env.example comme modèle
  • • Utiliser un service de gestion des clés en production
Service de gestion des clés
  • • AWS Secrets Manager
  • • HashiCorp Vault
  • • Azure Key Vault
  • • Faire tourner les clés régulièrement

Protection OWASP Top 10

1.Attaques par injection (SQL, NoSQL, injection de commandes)
2.Authentification échouée
3.Fuite de données sensibles
4.Entité externe XML (XXE)
5.Contrôle d’accès défaillant
6.Mauvaise configuration de sécurité
7.XSS, script intersite
8.Désérialisation non sécurisée
9.Utiliser des composants contenant des vulnérabilités connues
10.Journalisation et surveillance insuffisantes

Revue de code

La relecture de code est une étape importante pour garantir la qualité du code. Établissez des processus de relecture et des listes de contrôle clairs pour rendre les relectures plus efficaces.

Liste de contrôle de révision

Fonctionnalité
  • ☐ La fonctionnalité répond-elle aux exigences
  • ☐ Les cas limites sont-ils pris en charge
  • ☐ La gestion des erreurs est-elle complète
  • ☐ Les tests sont-ils suffisants
Performance
  • ☐ Y a-t-il des problèmes de performance ?
  • ☐ Les requêtes de base de données sont-elles optimisées
  • ☐ Y a-t-il une fuite de mémoire ?
  • ☐ L’utilisation du cache est-elle appropriée ?
Sécurité
  • ☐ La validation des entrées est complète
  • ☐ Des informations sensibles ont-elles fuité
  • ☐ La vérification des autorisations est-elle correcte ?
  • ☐ Les dépendances présentent-elles des failles de sécurité ?
Maintenabilité
  • ☐ Le code est-il clair et facile à lire ?
  • ☐ La convention de nommage est-elle appropriée ?
  • ☐ Les commentaires sont-ils suffisants
  • ☐ Le projet respecte-t-il les normes ?

Bonnes pratiques de revue

Revue en temps opportun: examiner dès que possible après la création de la PR afin d’éviter de bloquer le développement
Retour constructif: signaler les problèmes et proposer des améliorations, plutôt que de se contenter de critiquer
Revue par petits lots : limiter le volume de code examiné à moins de 400 lignes par revue
Vérification de l’automatisation: Utiliser CI/CD pour vérifier automatiquement le format, les tests et la sécurité

Amélioration continue

La qualité du code n'est pas une tâche ponctuelle, mais un processus d'amélioration continue. Mettez en place des indicateurs de qualité et des mécanismes de surveillance.

Indicateurs de qualité du code

Complexité cyclomatique
  • • Mesurer la complexité du code
  • • Objectif : < 10
  • • Outils : SonarQube, CodeClimate
Couverture du code
  • • La proportion de code couvert par les tests
  • • Objectif : > 80%
  • • Outils : Jest, Coverage.py, JaCoCo
Dette technique
  • • Code smells, code dupliqué
  • • Refactoriser régulièrement
  • • Outil : SonarQube

Vérifications automatisées (intégration CI/CD)

Exemple GitHub Actions :
name: Code Quality

on: [push, pull_request]

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
      - name: Install dependencies
        run: npm ci
      - name: Run linter
        run: npm run lint
      - name: Run tests
        run: npm test
      - name: Check coverage
        run: npm run test:coverage

Gestion de la dette technique

  • Identifier la dette: Utilisez des outils pour identifier automatiquement les code smells et le code dupliqué
  • Priorisation: Prioriser en fonction de l'ampleur de l'impact et du coût de correction
  • Refactorisation régulière: allouer un certain temps à la refactorisation dans chaque sprint
  • Enregistrer la dette: Le consigner dans un ticket ou dans la liste de la dette technique
  • Éviter une nouvelle dette technique: lors des revues de code, prêter attention à la dette technique

Résultats d’apprentissage

À la fin de ce chapitre, vous pourrez :

  • 1Maîtriser les conventions de code de différents langages (TypeScript, Python, Java, Go, etc.) et la configuration des outils
  • 2Maîtriser le versionnement avec Git, ainsi que les stratégies de branches et les processus de revue de code
  • 3Comprendre l’importance de la gestion des dépendances et maîtriser les stratégies d’audit de sécurité et de mise à jour
  • 4Maîtrisez la gestion des erreurs et les conventions de journalisation pour améliorer la robustesse du code
  • 5Comprendre l’optimisation des performances et les meilleures pratiques de sécurité, et écrire du code de haute qualité
  • 6Mettre en place un mécanisme de revue de code et d’amélioration continue pour améliorer la qualité du code de l’équipe