Le boilerplate est un code répétitif que les développeurs écrivent avec des modifications minimales dans chaque nouveau module ou projet. Il ne contient pas de logique métier unique, mais prépare simplement l'infrastructure : configuration, importation de bibliothèques, gestionnaires standard et classes DTO. Selon le CodeScene Engineering Productivity Report (2025), le boilerplate représente 20 à 40 pour cent de tout le code dans une application commerciale typique. Le problème principal de ce code n'est pas qu'il se répète, mais que chaque répétition est un point de défaillance : une erreur dans une copie ne se synchronise pas avec les autres, et les bugs se multiplient dans le projet. Automatiser la génération de boilerplate via la génération de code, les annotations et les macros est l'un des moyens les plus efficaces d'accélérer le développement sans perte de qualité.
Points clés
Le code boilerplate est constitué de fragments de code source qui se répètent dans différentes parties d'un projet avec des variations minimales. Le terme vient de l'industrie de l'imprimerie, où boilerplate désignait des blocs de texte pré-écrits pour les journaux qui ne nécessitaient pas de réécriture. En programmation, c'est tout code que vous êtes obligé d'écrire encore et encore pour satisfaire les exigences d'un framework, d'un langage ou d'une architecture.
Le boilerplate n'est pas une dette technique au sens classique — il ne contient pas de bugs et ne viole pas les principes SOLID. Cependant, il augmente la quantité de code à maintenir, tester et lire. Chaque ligne de boilerplate est un endroit potentiel pour une faute de frappe que le compilateur ne peut pas toujours détecter.
Selon le rapport JetBrains Developer Ecosystem (2025), 67 pour cent des développeurs considèrent le boilerplate comme la principale cause de baisse de productivité. Dans le développement mobile, ce chiffre est plus élevé : les projets Android en Java contiennent une quantité importante de code répétitif pour findViewById, Intents, les adaptateurs RecyclerView et les ContentProviders. Kotlin et Swift ont résolu une partie de ces problèmes par des moyens syntaxiques, mais le boilerplate n'a pas complètement disparu.
Lors de la conception de l'architecture, essayez de choisir des solutions qui minimisent le code répétitif. Par exemple, au lieu d'écrire manuellement l'implémentation Parcelable, utilisez @Parcelize dans Kotlin. Au lieu de fabriques pour ViewModel — Hilt avec @HiltViewModel. Chaque optimisation de ce type fait gagner des heures de développement à l'échelle du projet.
L'exemple le plus reconnaissable de boilerplate dans le développement Android est le RecyclerView.Adapter. Avant Kotlin et ViewBinding, chaque adaptateur nécessitait environ 80 à 100 lignes de code répétitif : onCreateViewHolder, onBindViewHolder, getItemCount, classe ViewHolder interne, constructeur, liaison de champs. Avec ViewBinding, le code s'est réduit, mais n'a pas complètement disparu.
class UserAdapter(
private val users: List<User>
) : RecyclerView.Adapter<UserAdapter.ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.item_user, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(
holder: ViewHolder,
position: Int
) {
holder.bind(users[position])
}
override fun getItemCount(): Int = users.size
class ViewHolder(itemView: View) :
RecyclerView.ViewHolder(itemView) {
fun bind(user: User) {
Glide.with(itemView)
.load(user.avatarUrl)
.into(itemView.avatar)
}
}
}
Un autre exemple illustratif est le mapping JSON en Java sans bibliothèques. L'analyse manuelle d'une réponse API nécessite d'écrire des dizaines de méthodes, chacune vérifiant la présence d'une clé, obtenant la valeur et l'assignant à un champ. Avec des bibliothèques comme Gson, Moshi ou Kotlin Serialization — c'est une annotation @Serializable.
Dans le développement iOS, le boilerplate classique est l'implémentation de CodingKey et Decodable pour chaque réponse API, surtout lorsque les clés JSON diffèrent des noms de propriétés en camelCase. Malgré la génération automatique de Codable, l'énumération manuelle des CodingKeys reste une source de code répétitif.
Utilisez la génération de code pour créer du boilerplate au moment de la compilation. Sous Android — Annotation Processing (KSP) pour Room, Dagger, Moshi. Sous iOS — Sourcery pour Codable et AutoMockable. Pour chaque heure consacrée à la configuration de la génération, vous économisez des jours de copie manuelle.
Le boilerplate nuit à un projet de trois manières : il ralentit l'écriture de nouvelles fonctionnalités, complique la lecture du code existant et crée des points de désynchronisation lors des modifications.
Le ralentissement du développement est évident : le développeur passe du temps à écrire du code qui ne contient pas de logique métier. Au lieu d'implémenter une nouvelle fonctionnalité (par exemple, ajouter un champ au profil utilisateur), il écrit une migration de BD, une classe DTO, un mapper vers l'entité domaine, un écran avec champ de saisie, une validation et des tests pour chaque couche. La majeure partie de ce travail est mécanique.
La désynchronisation est un problème plus insidieux. Lorsqu'une structure de données change à un endroit (par exemple, un champ est ajouté à une réponse API), le développeur doit mettre à jour le DTO, le mapper, le modèle, l'écran et les tests. Si un endroit est oublié, l'application compile mais plante à l'exécution ou — pire — affiche des données incorrectes sans erreur. Plus il y a de couches de boilerplate, plus le risque de désynchronisation est élevé.
Analysez le projet à la recherche de motifs répétés. Si vous voyez trois classes identiques avec des noms différents — c'est un candidat pour la génération. Introduisez la génération de code comme partie de la solution architecturale, et non comme une optimisation ponctuelle. Elle rentabilise à chaque nouveau module.
La génération de code est le moyen le plus fiable de lutter contre le boilerplate. Au lieu d'écrire manuellement du code répétitif, le développeur décrit des métadonnées (annotations, schémas, configurations), et le générateur crée le code prêt au moment de la compilation.
Dans l'écosystème Android, l'outil standard de génération de code est KSP (Kotlin Symbol Processing). Il remplace l'ancien KAPT et fonctionne plus rapidement grâce à l'accès direct à l'AST Kotlin sans génération de stubs Java. KSP est utilisé par Room (génération d'implémentations DAO), Moshi (génération de JsonAdapter), Glide (génération de classes de chargement cibles) et Dagger (génération du graphe DI).
@Entity(tableName = "users")
data class UserEntity(
@PrimaryKey val id: Long,
@ColumnInfo(name = "full_name") val name: String,
@ColumnInfo(name = "avatar_url") val avatarUrl: String
)
@Dao
interface UserDao {
@Query("SELECT * FROM users WHERE id = :id")
suspend fun getById(@Param("id") id: Long): UserEntity?
}
Dans le développement iOS, le rôle de la génération de code est assuré par Sourcery — un outil qui traite les modèles Stencil et génère du code Swift basé sur des annotations dans les commentaires. Scénarios typiques : AutoMockable (génération de mocks pour les tests), AutoCodable (implémentation Decodable sans CodingKeys), AutoEquatable et AutoLenses.
Pour les projets Flutter, le boilerplate est réduit par des générateurs via build_runner : json_serializable pour le mapping JSON, freezed pour les modèles immuables avec copyWith, retrofit_generator pour les clients API et injectable_generator pour DI. Chacun de ces générateurs transforme 10 à 20 lignes d'annotations en centaines de lignes de code prêt.
Les annotations et les macros sont une manière déclarative d'indiquer au compilateur ou au préprocesseur quel code générer. Le développeur n'écrit pas l'implémentation, mais marque seulement l'intention, et le générateur transforme le balisage en code prêt.
L'exemple le plus frappant est Lombok en Java (historiquement) et la data class de Kotlin. La data class dans Kotlin génère automatiquement equals, hashCode, toString, componentN et copy — en Java, cela nécessiterait environ 80 lignes de code écrit à la main ou l'utilisation de Lombok avec @Data. Kotlin a résolu le problème au niveau du langage, rendant le boilerplate implicite.
En Swift, un rôle similaire est joué par les macros (Swift Macros, introduites dans Swift 5.9). Au lieu d'écrire manuellement l'implémentation Codable, le développeur marque la structure avec @Codable — et le compilateur génère le code nécessaire. Autres macros intégrées : @Observable (état observable), @ResultBuilder (constructeurs de résultat) et @MainActor (répartition sur le thread principal).
@Codable
struct UserProfile {
let id: Int
let displayName: String
let avatarURL: URL
let bio: String?
}
// @Codable macro generates:
// extension UserProfile: Codable { }
// private enum CodingKeys: String, CodingKey {
// case id, displayName, avatarURL, bio
// }
Lors du choix entre la génération de code et les macros, privilégiez les macros si le langage les supporte. Les macros fonctionnent au niveau du compilateur, ne nécessitent pas de configuration de scripts de build, ne ralentissent pas la compilation (contrairement à Annotation Processing) et sont toujours synchronisées avec le code source. Si les macros ne sont pas disponibles — utilisez des générateurs externes via KSP, Sourcery ou build_runner.
Chaque langage et plateforme offre ses propres outils pour minimiser le boilerplate. Voici des pratiques spécifiques pour les principaux stacks de développement mobile.
| Plateforme | Outil / Technique | Ce qu'il remplace |
|---|---|---|
| Android / Kotlin | data class | equals, hashCode, toString, copy, componentN |
| Android / Kotlin | @Parcelize | Implémentation Parcelable |
| Android / Kotlin | ViewBinding / DataBinding | findViewById, ButterKnife |
| iOS / Swift | Codable + macros | Parsing JSON manuel, CodingKeys |
| iOS / Swift | Sourcery | AutoMockable, AutoEquatable, AutoLenses |
| Flutter / Dart | freezed + json_serializable | copyWith, classes scellées, equals/hashCode, JSON |
| Flutter / Dart | retrofit_generator | Client API avec requêtes et réponses typées |
Pour le frontend web (React Native / TypeScript), l'outil principal est la génération de types à partir de la spécification OpenAPI (openapi-typescript, swagger-codegen). Chaque endpoint reçoit automatiquement une requête et une réponse typées — le développeur n'a pas besoin de décrire manuellement les interfaces pour des centaines d'appels API.
Introduisez la génération de code dès les premières étapes du projet. Migrer un projet existant vers des générateurs est plus difficile que de concevoir avec eux dès le départ. Si le projet est déjà écrit — commencez par le point le plus douloureux : Java → Kotlin (data class), adaptateurs manuels → ListAdapter avec DiffUtil, mapping JSON manuel → Moshi / Kotlin Serialization.
Questions fréquentes
Le boilerplate n'est pas une dette, mais une redondance : le code est correct, mais il est trop abondant. La dette technique est une décision de compromis consciente qui devra être corrigée plus tard. Le boilerplate ne nécessite pas de correction — il nécessite de l'automatisation.
Non, dans les petits projets, le boilerplate peut être justifié par la simplicité : il est immédiatement visible et facile à modifier. Le problème se pose à l'échelle — lorsqu'il y a plus d'une dizaine de modules similaires, la copie manuelle cesse d'être efficace et il est temps d'introduire la génération.
Le code qui dépend de services externes avec une logique non standard (SDK personnalisés, protocoles propriétaires) est difficile à générer. Dans ces cas, le boilerplate est écrit manuellement mais isolé dans des modules séparés pour minimiser la dispersion dans le projet.
Pour les nouveaux projets, il est préférable de passer directement à Kotlin, où data class résout les mêmes tâches au niveau du langage. Si le projet reste en Java — Lombok reste le standard de facto, mais gardez à l'esprit qu'il nécessite un plugin IDE et peut entrer en conflit avec les nouvelles versions de Java.
Oui, la génération de code ajoute du temps à la compilation. KSP est plus rapide que KAPT mais ajoute tout de même des secondes ou des minutes à une compilation complète. Optimisation : utilisez des compilations incrémentielles et mettez en cache les résultats de génération entre les compilations.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi