🔝 Retour à la Table des matières
La structuration modulaire est une approche essentielle pour créer des projets PowerShell maintenables et évolutifs. Dans cette section, nous allons découvrir comment organiser votre code de manière professionnelle, même pour les projets complexes.
La structuration modulaire avancée consiste à organiser votre code PowerShell en composants distincts et réutilisables, chacun ayant une responsabilité spécifique. Cette approche facilite la maintenance, les tests et le partage de votre code.
Voici une structure de répertoires efficace pour un module PowerShell professionnel:
MonModule/
│
├── MonModule.psm1 # Point d'entrée principal du module
├── MonModule.psd1 # Manifeste du module
│
├── Public/ # Fonctions exportées (accessibles aux utilisateurs)
│ ├── Get-MaFonction.ps1
│ ├── Set-MaFonction.ps1
│ └── ...
│
├── Private/ # Fonctions internes (non exportées)
│ ├── Helper1.ps1
│ ├── Helper2.ps1
│ └── ...
│
├── Classes/ # Définitions de classes PowerShell (PS 5+)
│ ├── MaClasse1.ps1
│ └── MaClasse2.ps1
│
├── Configs/ # Fichiers de configuration
│ ├── default.json
│ └── settings.psd1
│
├── Tests/ # Tests Pester
│ ├── Public
│ │ └── Get-MaFonction.Tests.ps1
│ └── Private
│ └── Helper1.Tests.ps1
│
└── docs/ # Documentation
├── README.md
├── CHANGELOG.md
└── examples/
└── Exemple1.ps1
Voici un exemple de fichier .psm1 qui charge automatiquement toutes les fonctions:
# MonModule.psm1
# Charger les classes (doivent être chargées avant les fonctions)
$ClassesPath = Join-Path -Path $PSScriptRoot -ChildPath 'Classes'
if (Test-Path -Path $ClassesPath) {
$Classes = Get-ChildItem -Path $ClassesPath -Filter '*.ps1' -Recurse
foreach ($Class in $Classes) {
Write-Verbose "Chargement de la classe: $($Class.FullName)"
. $Class.FullName
}
}
# Charger les fonctions privées
$PrivatePath = Join-Path -Path $PSScriptRoot -ChildPath 'Private'
if (Test-Path -Path $PrivatePath) {
$PrivateFunctions = Get-ChildItem -Path $PrivatePath -Filter '*.ps1' -Recurse
foreach ($Function in $PrivateFunctions) {
Write-Verbose "Chargement de la fonction privée: $($Function.FullName)"
. $Function.FullName
}
}
# Charger les fonctions publiques et les exporter
$PublicPath = Join-Path -Path $PSScriptRoot -ChildPath 'Public'
if (Test-Path -Path $PublicPath) {
$PublicFunctions = Get-ChildItem -Path $PublicPath -Filter '*.ps1' -Recurse
# Charger chaque fonction
foreach ($Function in $PublicFunctions) {
Write-Verbose "Chargement de la fonction publique: $($Function.FullName)"
. $Function.FullName
}
# Exporter les fonctions pour qu'elles soient disponibles aux utilisateurs
Export-ModuleMember -Function $PublicFunctions.BaseName
}Le manifeste de module contient les métadonnées de votre module. Créez-le avec:
New-ModuleManifest -Path ".\MonModule\MonModule.psd1" `
-RootModule "MonModule.psm1" `
-ModuleVersion "1.0.0" `
-Author "Votre Nom" `
-Description "Description de votre module" `
-PowerShellVersion "5.1" `
-FunctionsToExport @('*') `
-CmdletsToExport @() `
-VariablesToExport @() `
-AliasesToExport @()Astuce: Remplacez
FunctionsToExport @('*')par la liste exacte de vos fonctions publiques pour une meilleure pratique.
- Organisation claire: Séparation des responsabilités et meilleure lisibilité du code
- Maintenabilité: Plus facile à déboguer et à mettre à jour
- Testabilité: Structure adaptée aux tests unitaires avec Pester
- Réutilisabilité: Fonctions modulaires utilisables dans différents contextes
- Meilleure collaboration: Plusieurs développeurs peuvent travailler sur différentes parties du module
- Facilité de distribution: Structure prête pour la publication sur PowerShell Gallery
Chaque fonction doit être placée dans son propre fichier .ps1, avec le même nom que la fonction:
# Public/Get-MaFonction.ps1
function Get-MaFonction {
<#
.SYNOPSIS
Description courte de la fonction
.DESCRIPTION
Description détaillée de la fonction
.PARAMETER Param1
Description du paramètre 1
.EXAMPLE
Get-MaFonction -Param1 "Valeur"
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Param1
)
begin {
# Code exécuté une fois au début
}
process {
# Code exécuté pour chaque élément du pipeline
Write-Verbose "Traitement de $Param1"
# Appel à une fonction privée
$resultat = Invoke-HelperPrivate -Input $Param1
# Retourner le résultat
return $resultat
}
end {
# Code exécuté une fois à la fin
}
}-
Installation locale pour les tests:
# Copier votre module dans un des dossiers de $env:PSModulePath $moduleDir = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules\MonModule" Copy-Item -Path ".\MonModule" -Destination $moduleDir -Recurse -Force
-
Importation du module:
Import-Module MonModule -Force -Verbose
-
Utilisation des fonctions:
Get-MaFonction -Param1 "Test"
- Un fichier par fonction: Facilite la maintenance et le suivi des modifications
- Documentation intégrée: Utilisez l'aide PowerShell pour documenter chaque fonction
- Préfixes cohérents: Utilisez des verbes approuvés par PowerShell (Get-, Set-, New-, etc.)
- Gestion des dépendances: Documentez et vérifiez les modules requis
- Gestion des versions: Suivez la gestion sémantique des versions (MAJOR.MINOR.PATCH)
- Tests unitaires: Créez des tests pour chaque fonction publique
- Logging: Utilisez Write-Verbose, Write-Debug et Write-Error de manière cohérente
Imaginons un petit module pour gérer les logs:
# Private/Format-LogMessage.ps1
function Format-LogMessage {
param (
[string]$Message,
[string]$Level,
[string]$Source
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
return "[$timestamp] [$Level] [$Source] - $Message"
}# Public/Write-Log.ps1
function Write-Log {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$Message,
[Parameter()]
[ValidateSet('INFO', 'WARNING', 'ERROR', 'DEBUG')]
[string]$Level = 'INFO',
[Parameter()]
[string]$LogPath = "$env:TEMP\PowerShell.log",
[Parameter()]
[string]$Source = 'PowerShell'
)
process {
# Utiliser notre fonction privée
$formattedMessage = Format-LogMessage -Message $Message -Level $Level -Source $Source
# Ajouter au fichier log
Add-Content -Path $LogPath -Value $formattedMessage
# Afficher en console avec couleur selon le niveau
switch ($Level) {
'ERROR' { Write-Host $formattedMessage -ForegroundColor Red }
'WARNING' { Write-Host $formattedMessage -ForegroundColor Yellow }
'INFO' { Write-Host $formattedMessage -ForegroundColor Green }
'DEBUG' { Write-Host $formattedMessage -ForegroundColor Gray }
}
}
}La structuration modulaire avancée transforme vos scripts PowerShell en véritables projets professionnels. En adoptant ces pratiques, vous créerez du code plus robuste, plus facile à maintenir et prêt pour le partage avec la communauté.
N'oubliez pas que même les projets complexes commencent simplement - vous pouvez débuter avec une structure basique (juste les dossiers Public et Private) et l'étendre au fur et à mesure que votre module grandit.
- Créez un module simple avec la structure décrite ci-dessus
- Ajoutez deux fonctions publiques et une fonction privée helper
- Créez un manifeste de module
- Testez le chargement et l'utilisation de votre module
📚 Ressources supplémentaires:
- PowerShell Gallery - Pour explorer d'autres modules bien structurés
- Plaster - Un générateur de templates pour créer des structures de modules
- BuildHelpers - Un module pour aider à la création de modules PowerShell
⏭️ Documentation de scripts et fonctions (.SYNOPSIS, .EXAMPLE, etc.)