add practices
parent
b3864b8413
commit
88adbc6865
38
README.md
38
README.md
|
@ -30,36 +30,24 @@ UI/UX :
|
||||||
|
|
||||||
*
|
*
|
||||||
* [Stocker localement les données de configuration non liées aux données du serveur](chapters/MBP_007_fr.md) // TODO à discuter car côté mobile, beaucoup des données statiques sont déjà sur l'appareil.
|
* [Stocker localement les données de configuration non liées aux données du serveur](chapters/MBP_007_fr.md) // TODO à discuter car côté mobile, beaucoup des données statiques sont déjà sur l'appareil.
|
||||||
* [Déployer un Android App Bundle (AAB) plutôt qu'un APK](chapters/MBP_008_fr.md)
|
* [Déployer un Android App Bundle (AAB) plutôt qu'un APK](chapters/MBP_008_fr.md) // TODO a reformuler
|
||||||
* [Supprimer les ressources non utilisées](chapters/MBP_009_fr.md)
|
* [Supprimer les ressources non utilisées](chapters/MBP_009_fr.md)
|
||||||
* [Minifier et obfusquer le code](chapters/MBP_010_fr.md)
|
* [Minifier le code](chapters/MBP_010_fr.md)
|
||||||
|
* [Ne pas redimensionner les images coté application](chapters/MBP_011_fr.md)
|
||||||
|
* [Éviter d'utiliser des images matricielles](chapters/MBP_012_fr.md)
|
||||||
|
|
||||||
|
// TODO
|
||||||
// TODO SavedStateHandle
|
// MAIN/IO thread ?
|
||||||
// Repository (stratégie offline)
|
// Repository (stratégie offline)
|
||||||
|
// Eviter image non vectoriel (/chapters/BP_023_fr.md)
|
||||||
|
// Etudier si l'usage de style/theme plutôt que paramètre individuel est plus efficace (BP_024_fr BP_025_fr)
|
||||||
|
// Utiliser les paramètres de style abrégés // [Utiliser les notations CSS abrégées](/chapters/BP_026_fr.md)
|
||||||
|
// Utiliser glide ou équivalent pour mettre en cache les images et éviter de les recharger
|
||||||
|
// Notifications
|
||||||
|
// ABI ??
|
||||||
|
// Feature play store
|
||||||
|
|
||||||
// TODO pas encore fait la suite
|
// TODO pas encore fait la suite
|
||||||
* [Proposer un traitement asynchrone lorsque c'est possible](/chapters/BP_008_fr.md) // TODO à voir si équivalent.
|
|
||||||
|
|
||||||
|
|
||||||
* [Choisir les technologies les plus adaptées](/chapters/BP_015_fr.md)
|
|
||||||
* [Utiliser certains forks applicatifs orientés "performance"](/chapters/BP_016_fr.md)
|
|
||||||
* [Choisir un format de données adapté](/chapters/BP_017_fr.md)
|
|
||||||
* [Limiter le nombre de domaine servant les ressources](/chapters/BP_018_fr.md)
|
|
||||||
* [Remplacer les boutons officiels de partage des réseaux sociaux](/chapters/BP_019_fr.md)
|
|
||||||
* [Découper les CSS](/chapters/BP_021_fr.md)
|
|
||||||
* [Limiter le nombre de CSS](/chapters/BP_022_fr.md)
|
|
||||||
* [Préférer les CSS aux images](/chapters/BP_023_fr.md)
|
|
||||||
* [Écrire des sélecteurs CSS efficaces](/chapters/BP_024_fr.md)
|
|
||||||
* [Grouper les déclarations CSS similaires](/chapters/BP_025_fr.md)
|
|
||||||
* [Utiliser les notations CSS abrégées](/chapters/BP_026_fr.md)
|
|
||||||
* [Fournir une CSS print](/chapters/BP_027_fr.md)
|
|
||||||
* [Favoriser les polices standards](/chapters/BP_029_fr.md)
|
|
||||||
* [Préférer les glyphs aux images](/chapters/BP_030_fr.md)
|
|
||||||
* [Valider les pages auprès du W3C](/chapters/BP_031_fr.md)
|
|
||||||
* [Externaliser les CSS et JavaScript](/chapters/BP_032_fr.md)
|
|
||||||
* [Ne pas redimensionner les images coté navigateur](/chapters/BP_034_fr.md)
|
|
||||||
* [Éviter d'utiliser des images matricielles pour l'interface](/chapters/BP_035_fr.md)
|
|
||||||
* [Optimiser les images vectorielles](/chapters/BP_036_fr.md)
|
* [Optimiser les images vectorielles](/chapters/BP_036_fr.md)
|
||||||
* [Utiliser le chargement paresseux](/chapters/BP_037_fr.md)
|
* [Utiliser le chargement paresseux](/chapters/BP_037_fr.md)
|
||||||
* [Utiliser le rechargement partiel d'une zone de contenu](/chapters/BP_038_fr.md)
|
* [Utiliser le rechargement partiel d'une zone de contenu](/chapters/BP_038_fr.md)
|
||||||
|
|
|
@ -33,7 +33,7 @@ Tout design d'interface doit être réfléchi en amont, en prenant en compte :
|
||||||
|
|
||||||
### Exemple
|
### Exemple
|
||||||
|
|
||||||
// TODO je ne comprends pas bien l'exemple. Il manque une illustration ?. A reformuler
|
// TODO je ne comprends pas bien l'exemple.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,22 +20,23 @@
|
||||||
|
|
||||||
### Description
|
### Description
|
||||||
|
|
||||||
Lorsqu'une personne navigue d'une vue à une autre au sein d'une application, mais également entre plusieurs applications sur son mobile, ces vues transitionnent entre différents états. Selon ces changements d'état, pour optimiser l'usage de la mémoire du téléphone, le système va effectuer des opérations telles que : libérer partiellement la mémoire si l'application passe en arrière-plan, supprimer complétement les données de la mémoire si l'utilisateur quitte la vue en cours en appuyant par exemple sur le bouton retour. Ces changements d'état sont matérialisés par le cycle de vie.
|
Lorsqu'une personne navigue d'un écran à un autre au sein d'une application, mais également entre plusieurs applications sur son mobile, ces applications transitionnent entre différents états. Selon ces changements d'état, pour optimiser l'usage de la mémoire du téléphone, le système va effectuer des opérations telles que : libérer partiellement la mémoire si l'application passe en arrière-plan, supprimer les données en mémoire de l'écran en cours si l'utilisateur quitte celui-ci en appuyant par exemple sur le bouton retour.
|
||||||
|
|
||||||
Il convient d'optimiser l'accès aux données utilisées faites par la vue, afin d'éviter d'effectuer des requêtes en base de données locale ou sur le réseau à chaque changement d'état.
|
|
||||||
|
Il convient d'optimiser l'accès aux données faites depuis une activité selon son cycle de vie, afin d'éviter d'effectuer inutilement des requêtes en base de données locale ou sur le réseau.
|
||||||
|
|
||||||
Il existe plusieurs bonnes pratiques à appliquer à différents niveaux :
|
Il existe plusieurs bonnes pratiques à appliquer à différents niveaux :
|
||||||
- À l'échelle de la vue :
|
- À l'échelle de la vue :
|
||||||
- En utilisant correctement les callbacks du cycle de vie fournies par les composants `Activity` ou `Fragment`.
|
- En utilisant correctement les callbacks du cycle de vie fournies au sein d'une `Activity`.
|
||||||
- À l'échelle du `ViewModel` :
|
- À l'échelle du `ViewModel` :
|
||||||
- En utilisant une classe de type `ViewModel` (par exemple via l'implémentation fournie par l'API **Jetpack ViewModel**) ayant un cycle de vie plus long.
|
- En utilisant une classe de type `ViewModel` (par exemple via l'implémentation fournie par l'API **Jetpack ViewModel**) avec un cycle de vie plus long que celui de la vue.
|
||||||
|
|
||||||
#### A l'échelle de la vue :
|
#### A l'échelle de la vue :
|
||||||
|
|
||||||
Au sein d'une classe de type `Activity` ou `Fragment`, il est courant de surcharger une ou plusieurs méthodes du cycle de vie afin d'initialiser et d'adapter l'état de la vue (via les méthodes `onCreate`, `onResume`, `onPause`,`onStop`, etc.). Il est important d'éviter de récupérer inutilement les données depuis la base de données locale ou le réseau à chaque fois que la vue redevient visible et utilisable (état `RESUMED`), c'est-à-dire au sein de la fonction `onResume`.
|
Au sein d'une classe de type `Activity`, il est courant de surcharger une ou plusieurs méthodes du cycle de vie afin d'initialiser et d'adapter l'état de la vue (via les méthodes `onCreate`, `onResume`, `onPause`,`onStop`, etc.). Il est important d'éviter de récupérer inutilement les données depuis la base de données locale ou le réseau à chaque fois que la vue redevient visible et utilisable (état `RESUMED`), c'est-à-dire au sein de la fonction `onResume`.
|
||||||
Il convient plutôt d'initialiser l'état de la vue au sein de la fonction `onCreate` et de récupérer les données dont elle a besoin soit dans l'état `CREATED`, soit dans l'état `STARTED`.
|
Il convient plutôt d'initialiser l'état de la vue au sein de la fonction `onCreate` et de récupérer les données dont elle a besoin soit dans l'état `CREATED`, soit dans l'état `STARTED`.
|
||||||
|
|
||||||
Note : Dans certaines situations, il est conseillé de développer ses propres composants "lifecycle aware" afin d'être notifié de la même façon de ces changements d'états, afin de rendre le code plus maintenable.
|
Note : Dans certaines situations, il est conseillé de développer ses propres composants "lifecycle aware" afin d'être notifié de la même façon de ces changements d'états et de rendre le code plus maintenable.
|
||||||
|
|
||||||
#### A l'échelle du `ViewModel`
|
#### A l'échelle du `ViewModel`
|
||||||
|
|
||||||
|
@ -94,7 +95,7 @@ sealed interface ProfileUIState {
|
||||||
### Principe de validation
|
### Principe de validation
|
||||||
|
|
||||||
| Le nombre ... | est inférieur ou égal à |
|
| Le nombre ... | est inférieur ou égal à |
|
||||||
|--------------------------------------------------------------------------------------------------|:-----------------------:|
|
|----------------------------------------------------------------------------------------------------|:-----------------------:|
|
||||||
| d'écran effectuant des chargements de données à chaque fois que la vue passe dans l'état `RESUMED` | 0% |
|
| d'écran effectuant des chargements de données à chaque fois que la vue passe dans l'état `RESUMED` | 0% |
|
||||||
| d'écran rechargeant l'ensemble des données lors d'un changement de configuration | 0% |
|
| d'écran rechargeant l'ensemble des données lors d'un changement de configuration | 0% |
|
||||||
| d'écran n'utilisant pas de ViewModel ou équivalent pour maintenir l'état de la vue | 0% |
|
| d'écran n'utilisant pas de ViewModel ou équivalent pour maintenir l'état de la vue plus longtemps | 0% |
|
|
@ -29,14 +29,14 @@ Lorsqu'une personne navigue entre plusieurs applications sur son mobile, ces app
|
||||||
Au sein de ses deux callbacks, une bonne pratique est de libérer ou d'ajuster les ressources consommatrices initialisées précédemment.
|
Au sein de ses deux callbacks, une bonne pratique est de libérer ou d'ajuster les ressources consommatrices initialisées précédemment.
|
||||||
|
|
||||||
Quelques exemples de traitements consommateurs :
|
Quelques exemples de traitements consommateurs :
|
||||||
* L'affichage d'une animation
|
* L'affichage d'une animation.
|
||||||
* La lecture d'une vidéo ou d'un son.
|
* La lecture d'une vidéo ou d'un son.
|
||||||
* L'usage des capteurs du téléphone : le GPS, le gyroscope.
|
* L'usage des capteurs du téléphone : le GPS, le gyroscope.
|
||||||
* L'usage de protocol de connectivité : Bluetooth, Wifi, NFC, etc.
|
* L'usage de protocol de connectivité : Bluetooth, Wifi, NFC, etc.
|
||||||
|
|
||||||
### Exemple
|
### Exemple
|
||||||
* Soit une application utilisant la position GPS du téléphone. Lorsque l'activité n'est plus visible, il faut désactiver la mise à jour de la position dans la fonction `onStop` ou si cela n'est pas possible, changer la granularité de mise à jour de la position de "fine" à "grossière".
|
* Soit une application utilisant la position GPS du téléphone. Lorsque l'activité n'est plus visible, il faut désactiver la mise à jour de la position dans la fonction `onStop`. Si cela n'est pas possible, une alternative est de changer la granularité de mise à jour de la position de "fine" à "grossière".
|
||||||
* Soit une activité `PhotoActivity` qui utilise l'appareil photo. Lorsqu'une autre activité prend le focus sur celle-ci par exemple sous forme de modale, mais que la première activité restent visible dessous (dans l'état `PAUSED`), il faut appeler la fonction `camera?.release()` dans la callback `onPause`.
|
* Soit une activité `PhotoActivity` qui utilise l'appareil photo. Lorsqu'une autre activité prend le focus sur celle-ci par exemple sous forme de modale, mais que la première activité restent visible dessous (elle est donc dans l'état `PAUSED`), il faut appeler la fonction `camera?.release()` dans la callback `onPause`.
|
||||||
|
|
||||||
### Principe de validation
|
### Principe de validation
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
Supprimer les ressources et les classes non utilisées permet de réduire la taille de l'application.
|
Supprimer les ressources et les classes non utilisées permet de réduire la taille de l'application.
|
||||||
|
|
||||||
Il existe plusieurs moyens d'appliquer cela :
|
Il existe plusieurs moyens d'appliquer cela :
|
||||||
- Utiliser le linter inclus dans Android Studio qui détecte les ressources (`res/`) non utilisées et les supprimer manuellement.
|
- Utiliser le linter inclus à Android Studio qui détecte les ressources (`res/`) non utilisées et les supprimer manuellement.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
res/layout/item_row.xml: Warning: The resource R.layout.item_row appears
|
res/layout/item_row.xml: Warning: The resource R.layout.item_row appears
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## Minifier et optimiser le code
|
## Minifier le code
|
||||||
|
|
||||||
### Identifiants
|
### Identifiants
|
||||||
|
|
||||||
|
@ -22,16 +22,16 @@
|
||||||
|
|
||||||
### Description
|
### Description
|
||||||
|
|
||||||
Utiliser un outil de minification et d'optimisation de code permet de réduire considérable la taille de l'application.
|
Utiliser un outil de minification de code permet de réduire considérable la taille d'une application.
|
||||||
Sur android, cet outil se décompose en quatre processus :
|
Sur Android, cet outil se décompose en quatre processus :
|
||||||
-La minification, qui consiste à supprimer les espaces inutiles, les commentaires, les sauts de ligne, les délimiteurs de blocs et ainsi réduire la taille de l'application finale.
|
1. La suppression du code non utilisée (appelé aussi "Code shrinking"). Ce processus supprime en particulier le code non utilisé au sein des bibliothèques tierces incluses dans notre projet, par exemple si notre code n'utilise qu'une petite partie de celles-ci. (paramètre `isMinifyEnabled`).
|
||||||
- La suppression des ressources non utilisées dans notre code mais également dans les bibliothèques tierces incluses dans notre projet, par exemple si notre code n'utilise qu'une petite partie de celles-ci.
|
2. L'optimisation. Ce processus inspecte et optimize le code pour supprimer plus en détail les parties du code qui ne sont jamais exécutés. Par exemple il peut détecter que la branche `else` d'une condition n'est jamais empruntée, et donc la supprimer du code compilé.
|
||||||
- L'obfuscation. Ce processus réduit le nom des classes et de ses membres, augmentant la sécurité et réduisant par la même occasion la taille des fichiers. Par exemple la classe : `com.monpackage.MaClass` devient une fois compilée : `a.a.B`
|
3. L'obfuscation. Ce processus réduit le nom des classes et de ses membres, augmentant la sécurité et réduisant par la même occasion la taille des fichiers. Par exemple la classe : `com.monpackage.MaClass` devient une fois compilée : `a.a.B`. (paramètre `isMinifyEnabled`).
|
||||||
- L'optimisation. Ce processus inspecte et optimize le code pour supprimer le code qui n'est jamais exécutée. Par exemple il peut détecter que la branche `else` d'une condition n'est jamais empruntée, et donc la supprimer du code compilé.
|
4. La suppression des ressources non utilisées dans notre code️ appelé aussi "Ressource shrinking" (paramètre `isShrinkResources`). Ce processus ne s'applique que si le paramètre `isMinifyEnabled` est activé.
|
||||||
|
|
||||||
Pour activer et configurer ces processus, il faut activer les paramètres `isShrinkResources` et `isMinfyEnabled` dans le fichier Gradle de l'application, dans les paramètres du build qui sera déployé. Au-delà de ses paramètres, il faut ensuite spécifier les processus qui doivent s'appliquer et sur quelles classes dans le fichier `proguard-rules.pro` du projet.
|
|
||||||
|
|
||||||
|
Pour activer et configurer ces processus, il faut activer les paramètres `isShrinkResources` et `isMinfyEnabled` dans le fichier Gradle de l'application, dans les paramètres du build qui sera déployé. Au-delà de ses paramètres, il faut ensuite spécifier les processus doivent s'appliquer et sur quelles classes dans le fichier `proguard-rules.pro` du projet.
|
||||||
|
|
||||||
|
Cette pratique permet généralement de réduire la taille finale de l'application de moitié.
|
||||||
|
|
||||||
### Exemple
|
### Exemple
|
||||||
|
|
||||||
|
@ -60,5 +60,5 @@ android {
|
||||||
### Principe de validation
|
### Principe de validation
|
||||||
|
|
||||||
| Le nombre ... | est inférieur ou égal à |
|
| Le nombre ... | est inférieur ou égal à |
|
||||||
|------------------------------------|:-----------------------:|
|
|-----------------------------------|:-----------------------:|
|
||||||
| de fichiers non minifiés/optimisés | 25 |
|
| de fichiers non minifiés | 25 |
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
## Ne pas redimensionner les images coté application
|
||||||
|
|
||||||
|
### Identifiants
|
||||||
|
|
||||||
|
| GreenIT | V2 | V3 | V4 |
|
||||||
|
|:-------:|:----:|:----:|:----:|
|
||||||
|
| 93 | 20 | 34 | |
|
||||||
|
|
||||||
|
### Catégories
|
||||||
|
|
||||||
|
| Cycle de vie | Tiers | Responsable |
|
||||||
|
|:---------:|:----:|:----:|
|
||||||
|
| 3. Réalisation (fabrication / développement) | Utilisateur/Terminal | Utilisateur |
|
||||||
|
|
||||||
|
### Indications
|
||||||
|
|
||||||
|
| Degré de priorité | Mise en oeuvre | Impact écologique |
|
||||||
|
|:-------------------:|:-------------------------:|:---------------------:|
|
||||||
|
| 4 | 4 | 4 |
|
||||||
|
|
||||||
|
|Ressources Economisées |
|
||||||
|
|:----------------------------------------------------------:|
|
||||||
|
| Processeur / Réseau |
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
Ne pas redimensionner les images côté application. Cette approche impose en effet de transférer ces images dans leur taille originale, gaspillant ainsi de la bande passante et des cycles CPU.
|
||||||
|
|
||||||
|
### Exemple
|
||||||
|
|
||||||
|
Une image de 350 × 300 pixels encodée en PNG 24 pèse 41 Ko. Redimensionnée dans le code, la même image affichée en vignette à 70 × 60 pixels pèse toujours 41 Ko, alors qu’elle ne devrait pas dépasser 3 Ko ! Soit 38 Ko téléchargés à chaque fois pour rien…
|
||||||
|
|
||||||
|
La meilleure solution consiste à ce que le serveur génére des images à la taille à laquelle elles sont affichées.
|
||||||
|
|
||||||
|
### Principe de validation
|
||||||
|
|
||||||
|
| Le nombre ... | est inférieur ou égal à |
|
||||||
|
|---------------------------------------------|:-------------------------:|
|
||||||
|
| d'images redimensionnées dans l'application | 0 |
|
|
@ -0,0 +1,54 @@
|
||||||
|
## Eviter d'utiliser des images matricielles
|
||||||
|
|
||||||
|
### Identifiants
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
### Catégories
|
||||||
|
|
||||||
|
| Cycle de vie | Tiers | Responsable |
|
||||||
|
|:---------:|:----:|:----:|
|
||||||
|
| 5. Utilisation | Utilisateur/Terminal | Utilisateur |
|
||||||
|
|
||||||
|
### Indications
|
||||||
|
|
||||||
|
| Degré de priorité | Mise en oeuvre | Impact écologique |
|
||||||
|
|:-------------------:|:-------------------------:|:---------------------:|
|
||||||
|
| 4 | 4 | 4 |
|
||||||
|
|
||||||
|
|Ressources Economisées |
|
||||||
|
|:----------------------------------------------------------:|
|
||||||
|
| Réseau |
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
Choisir le bon format d’image est crucial pour réduire la taille de l'application.
|
||||||
|
Par ailleurs, avec la multiplication des terminaux, des tailles d’écran et l’augmentation de leur résolution, une approche vectorielle
|
||||||
|
doit être privilégiée par rapport à des images matricielles.
|
||||||
|
Grâce à cette bonne pratique, l’interface est indépendante de la résolution de l’écran. On limite donc aussi la dette technique.
|
||||||
|
La première règle consiste à remplacer les images matricielles (GIF, PNG, JPEG, WebP, etc.) par des images vectoriels (SVG), ou des icônes inclues dans la police de caractères.
|
||||||
|
S’il n’est pas possible d’utiliser ce format, il convient de convertir a minima les images de type GIF, PNG et JPEG en image de type WebP. En effet, ce dernier offre une compression meilleure et supporte également la gestion de transparence depuis Android 4.3 (API Level 18).
|
||||||
|
|
||||||
|
Android Studio permet de transformer rapidement des images de type PNG ou JPEG en format WebP. Il suffit de faire clic droit sur le fichier de l'image ou un répertoire contenant plusieurs images, et sélectionner "Convert to WebP".
|
||||||
|
|
||||||
|
Note : Il est intéressant de noter qu'un fichier SVG n'est pas inclus tel quel au sein d'un projet Android, mais qu'il est transformé en un fichier XML interprétable par le SDK Android via l'outil d'import d'Android Studio. Ce dernier va optimiser le contenu de ce fichier XML en supprimant les attributs inutiles et les commentaires qui pouvaient être inclus dans le fichier SVG.
|
||||||
|
|
||||||
|
### Exemple
|
||||||
|
|
||||||
|
|
||||||
|
![Différentes formes géométriques qui se superposent.](demo-image-format.png)
|
||||||
|
|
||||||
|
Cette image de 198 × 198 pixels pèse :
|
||||||
|
- 118 Ko dans un format matriciel non compressé ;
|
||||||
|
- 6,5 Ko en JPEG (compression à 90 %) ;
|
||||||
|
- 3,8 Ko en PNG ;
|
||||||
|
- 0,7 Ko en WebP (qualité d'encodage à 75%);
|
||||||
|
- 0,7 Ko en SVG.
|
||||||
|
|
||||||
|
Le format vectoriel est, dans ce cas précis, 5 à 10 fois moins lourd qu’un format matriciel tout en pouvant être redimensionné à l’infini.
|
||||||
|
|
||||||
|
### Principe de validation
|
||||||
|
|
||||||
|
| Le nombre ... | est inférieur ou égal à |
|
||||||
|
|-------------------|:-----------------------:|
|
||||||
|
| d'images matricielles | 5 |
|
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
Loading…
Reference in New Issue