Conventions, pratiques et attitudes de codage Java pour améliorer la lisibilité et la fiabilité. Veuillez l'utiliser après avoir prêté attention aux points suivants.
Premièrement, seules les règles sont présentées. Voir ci-dessous pour une explication.
boolean est déroutant lorsqu'il est utilisé comme argument de méthode. Vous ne pouvez pas comprendre sans vérifier les spécifications de la méthode. Si vous utilisez enum, la signification est facile à comprendre. Peu importe s'il est utilisé localement dans la méthode ou la valeur de retour de la méthode.
boolean isActive = true;
Ce qui suit est plus facile à comprendre que ce qui précède.
boolean ACTIVE = true; boolean IN_ACTIVE = false; boolean status = IN_ACTIVE;
Vous pouvez comprendre la signification même si vous l'utilisez comme argument de méthode Cependant, passer un booléen avec une signification différente n'entraîne pas d'erreur de compilation. En fait, l'énumération est bonne.
La raison est difficile à comprendre en lisant la source. Il est particulièrement difficile de comprendre quand la condition négative est définie. Il est difficile à comprendre lorsqu'il est combiné avec d'autres conditions.
boolean notFound = true; if (! notFound) {// ← déroutant // Traitement une fois trouvé. }
La raison est difficile à comprendre avec String. Le nom est String, l'adresse est String, le nom de la société est String et le nom du service est String. Même si vous faites une affectation étrange ou faites une erreur dans l'argument, une erreur de compilation ne se produira pas. Je veux vraiment utiliser la classe CompanyName extend String {}, mais je ne peux pas. ⇒String est final. Donc class CompanyName {valeur de chaîne privée; ...}.
Mais à tous égards, essayer de le faire est assez ennuyeux. Vous devez redéfinir les méthodes de String (bien que vous n'ayez besoin que de ce dont vous avez besoin). Lors de l'utilisation d'une bibliothèque externe, il est toujours nécessaire d'effectuer une conversion / conversion inverse.
Je ne comprends pas la signification de null lors de l'attribution ou de la transmission à une méthode, en particulier lors de la transmission à une méthode.
class Address { // Traitement omis } class MyClass { public void method(Address addr) { // Traitement omis } }
// Cela rend difficile de comprendre ce que null a été passé MyClass myObj = new MyClass(); myObj.method (null); // ⇒ Je ne sais pas
// Vous devez faire comme suit Address Address_IS_NULL = (Address)null; myObj.method (Address_IS_NULL); // ⇒ Facile à comprendre
Remarque, il semble préférable de définir la définition nulle dans la classe (adresse dans cet exemple). Citer comme Address.IS_NULL Mais lorsque vous n'êtes pas en charge, faites ce qui précède.
S'il est entier, il ne sera pas vérifié même si une valeur non valide est attribuée. Cependant, si le système existant utilise la constante int, il est inévitable d'utiliser la constante int.
// Définition du genre en int final int GENDER_MALE = 1; final int GENDER_FEMALE = 2; int intGender = GENDER_MALE; intGender = 100; // ⇒ Aucune erreur du compilateur
// En fait, il vaut mieux utiliser enum que ce qui précède Gender enumGender = Gender.MALE;
// ce sera faux new Integer(0) == new Integer(0) // Je ne sais pas si c'est un bug.
Cela revient également à ne pas utiliser la constante int. Elle n'est pas vérifiée même si une valeur non valide est affectée. Cependant, si le système existant utilise la constante String, cela est inévitable.
final String GENDER_MALE = "male"; final String GENDER_FEMALE = "female"; String stringGender = GENDER_FEMALE; stringGender = "abc"; // ⇒ Aucune erreur de compilation
// Rendez-le plus énuméré que ci-dessus Gender enumGender = Gender.FEMALE;
Supplément. Sur la base de données, c'est une valeur numérique ou un caractère, et si c'est une énumération sur la mémoire, c'est incompatible. Si vous implémentez static fromInt (fromString) dans l'énumération et implémentez toInt (toString), vous pouvez créer une classe à usage général qui effectue la conversion.
Il peut être difficile de décider d'utiliser un tableau ou une liste, mais c'est une bonne idée de se prononcer sur un tel principe.
Si vous écrivez simplement une constante, vous n'en comprenez pas la signification. Lors de la modification, il est possible de modifier une autre partie de la même valeur.
// Je ne comprends pas cela, vous pouvez changer le sexe par erreur en changeant 1 de statut en une autre valeur. int status = 1; // Je ne comprends pas la signification int gender = 1; // je ne comprends pas le sens
// Si vous faites ce qui suit, ce sera plus facile à comprendre et il n'y aura aucune erreur à changer. final int STATUS_ACTIVE = 1; final int STATUS_INSCTIVE = 2; final int GENDER_MALE = 1; final int GEDNER_FEMALE = 2; status = STATUS_ACTIVE; // Facile à comprendre gender = GENDER_MALE; // Facile à comprendre
Remarque, cet exemple devrait vraiment être changé en enum
Une variable ne doit être utilisée que pour une seule signification. Je sais, mais sachez qu'il n'est pas impossible de faire des erreurs lorsque vous êtes occupé.
Si vous affectez à une variable plusieurs fois, la valeur sera difficile à comprendre lors du traitement avec cette variable. Ce que l’on appelle la «réaffectation» est délicat. Par exemple, ce qui suit conviendrait. Attribuez des valeurs aux variables d'instance et aux variables associées lors du traitement des instances l'une après l'autre dans une boucle. Définissez une valeur initiale, mettez à jour la valeur dans certaines conditions, puis procédez à l'utilisation de cette variable. Un exemple de mauvaise affaire. Après avoir attribué une valeur à une variable, procédez au traitement à l'aide de cette variable, puis affectez-la à une valeur et procédez au traitement en utilisant cette variable. Voir "Bloquer le traitement en masse".
Pour faciliter la compréhension du fait que l'intention est un paramètre de type Si l'intention ci-dessus peut être réalisée, d'autres méthodes peuvent être utilisées, mais ce domaine n'est pas en conflit avec d'autres règles.
S'il s'agit d'une chaîne, str etc. Ceci est particulièrement bon pour les classes courantes
La raison est de saisir rapidement la liste des champs. Dans la classe d'instance, en plus des champs, des méthodes de routine telles que setter / getter sont définies. En regardant la source, je veux être en mesure de saisir instantanément quel type de champs il y a en regardant la partie de début. Par conséquent, écrivez uniquement la définition de champ au début et écrivez le commentaire du champ sur une ligne sans interruption.
Dans la classe logique, je veux connaître la méthode publique. Les champs utilisés pour le traitement interne sont inutiles du point de vue de l'utilisation de la classe, ils sont donc décrits à la fin. Les variables / constantes publiques doivent être écrites au début, mais les constantes privées doivent être écrites à la fin.
S'il est clairement référencé de l'extérieur du propre package, rendez-le public. Les classes autres que (pour le moment) n'ont pas de public. Si nécessaire, rendez-le public à ce moment-là, mais à ce moment-là, il y aura un moment pour réfléchir "si cela devrait être public ou non?" Comme effet négatif, le responsable d'un autre package peut créer une classe similaire sans savoir qu'il existe une classe qui peut être utilisée.
Ce n'est pas essentiel, mais c'est du bon sens. Normalement, le constructeur ne fait pas beaucoup de traitement, donc si vous ajoutez un autre traitement, d'autres personnes peuvent mal le comprendre.
Les champs ne sont pas initialisés sur la ligne de déclaration. Faites-le dans la méthode d'initialisation. Il sera plus facile de comprendre ce qui est initialisé. Utile lorsque la réinitialisation est nécessaire. La finalité est d'empêcher la substitution. Remplacer la méthode appelée dans le constructeur la rend étrange. Détails omis. Notez que le nom de la méthode d'initialisation de la classe héritée doit être considéré séparément.
Naturellement pour éviter les malentendus. Ne faites pas le nom d'une autre méthode souhaitée comme la méthode d'initialisation.
constructeur Lorsqu'il n'y a pas de traitement, il est correct de préciser ce fait. Cependant, il devrait y avoir un traitement si l'initialisation du champ est transformée en méthode. Le constructeur de la classe héritée ne peut pas être traité On peut voir qu '«après avoir examiné si le traitement était nécessaire, nous avons décidé qu'il n'était pas nécessaire».
Méthode Existe-t-il une méthode sans traitement? ⇒ C'est possible lorsque la méthode est écrasée. Décrire comme «aucun traitement» ⇒ Il est important de décrire dans ce cas. On peut voir qu '«après avoir examiné si le traitement était nécessaire, nous avons décidé qu'il n'était pas nécessaire».
Dans de nombreux cas, ce n'est pas nécessaire, mais pour le moment, le principe de «créer» est utilisé. Il peut être jugé individuellement comme "non requis dans cette classe".
Pensez à le passer à une autre classe logique en tant qu'interface Ne laissez pas la classe remise faire ce que vous voulez. Vous pouvez clairement voir ce que la classe transférée doit faire. Vous devriez (peut-être) créer une interface juste pour cela.
La raison est la suivante: s'il s'agit d'une classe, le nom de la classe est décrit, il est donc facile de comprendre de quelle constante il s'agit et où elle est définie.
Attention, c'est un cas assez exceptionnel. Il existe une constante statique dans la classe commune, et il est pratique d'utiliser un bloc statique lors de son initialisation. Il est exécuté au moment où il a été utilisé pour la première fois, il n'est donc pas nécessaire de prendre en compte le calendrier d'exécution. Cependant, une exception ne peut pas être émise dans un bloc statique (← une erreur de compilation se produit). Si une exception est inévitablement générée lors du traitement du bloc statique, attrapez-la en interne, affichez un journal et lancez une RuntimeException, et la compilation passera.
Les classes qui ne sont pas utilisées ailleurs sont définies localement. C'est ennuyeux et trompeur lorsque vous sortez. Identique à limiter les variables à une portée aussi restreinte que possible.
La raison en est que la liste de Comparator peut être trouvée immédiatement dans JavaDoc. . // Faites ce qui suit. interface OurComparator extends Comparator {} class OurClass implements OurComparator { .... }
La raison en est la suivante Vous pouvez voir immédiatement ce que vous implémentez / héritez par nom Affiché à côté dans Eclipse.
// Par exemple: / ** Employé. * / class Staff {} /** La gestion. */ class StaffManager extends Staff{}
problème Le nom ne semble pas correct en anglais. S'il existe plusieurs implémentations / héritages, il est nécessaire de se limiter à un. S'il existe plusieurs hiérarchies, le nom deviendra de plus en plus long.
Lorsque vous créez une classe dérivée, vous n'aurez peut-être pas besoin des méthodes de classe de base. Vous pouvez empêcher le mauvais appel en remplaçant cette méthode et en lançant une RuntimeException.
C'est banal, mais ça ne semble pas être fait. Moi aussi. Alors faites une règle et ne l'oubliez pas.
C'est utile pour le débogage, donc je veux vraiment l'implémenter. Vous pouvez créer une aide à usage général en connectant les champs obligatoires à String.
Celles-ci sont souvent inutiles. Faites une règle pour l'implémenter et jugez individuellement qu '"il n'est pas nécessaire de l'implémenter dans cette classe".
Surtout lorsque la valeur de retour est booléenne. C'est le même que le nom de la variable booléenne et est difficile à comprendre. Cela peut ne pas être difficile à comprendre, donc un jugement individuel est nécessaire.
Dans le cas de vide, le traitement lorsque les données sont obtenues et quand elles ne le sont pas peut être le même.
Cependant, il vaut mieux porter un jugement explicite. Décidons lequel utiliser dans le système. Consultez «Créer une méthode statique dans la classe d'origine pour déterminer si la valeur de retour est normale».
Il appartient à l'appelant de décider quoi faire après avoir renvoyé la valeur de retour. On ne sait pas si la méthode sera interprétée comme prévu.
// Faites ce qui suit pour améliorer encore un peu class MyClass { / ** Méthode d'appel * / public String method(String str) { // Quelques traitements return null; // une erreur s'est produite } / ** Méthode pour déterminer la valeur de retour * / public static boolean errorHappened(String value) { return (value == null); } }
MyClass myObj = new MyClass(); String returnValue = myObj.method("aaaa"); if (MyClass.errorHappened(returnValue)) { // La gestion des erreurs }
Je sais qu'il y a des critiques d '«excès».
class MyClass { public boolean check(String str) { // Quelque chose à faire return true; } public boolean checkNormalEnded(String str) { // Quelque chose à faire return true; } }
MyClass myObj = new MyClass(); // Je ne comprends pas la signification de l'instruction if. if (myObj.check("aaaa")) { // Quelques traitements }
// Je comprends le sens ici if (myObj.checkNormalEnded("aaaa")) { // Quelques traitements }
Il existe un risque de falsification si vous renvoyez la liste interne, etc. Alors retournez la copie. Serpentine, ArrayList est clonable mais List n'est pas clonable
Vous allez créer une classe pour la valeur de retour. Mais si la classe ne semble pas disponible ailleurs, c'est très décevant. Mais généralement, supportez les regrets et faites-le.
// Si vous dites "Je n'aime vraiment pas ça" dans la section précédente, procédez comme suit class Box { public Object[] getSize() { // Le premier est la hauteur, le suivant est la largeur return new Integer[]{5,10}; } public static Integer getHeight(Object[] values) { return (Integer)values[0]; } public static Integer getWidth(Object[] values) { return (Integer)values[1]; } }
Box box = new Box(); Object[] values = box.getSize(); int width = Box.getWidth(values); int height = Box.getHeight(values);
Il n'y a pas besoin de nouveau, la signification est facile à comprendre car le nom de la classe est écrit Je pense que c'est du bon sens de faire cela, mais parfois je vois quelque chose qui est une méthode interne.
Vous pouvez distinguer en vérifiant les arguments, mais c'est gênant Doit être distinguable par le nom de la méthode
Maintenant une reconnaissance naturelle Si vous avez besoin de vitesse, faites-le.
Pensez à ce qui suit Y a-t-il une logique plus simple? L'idée n'est-elle pas fausse? Est-ce la logique nécessaire en premier lieu? Si vous en avez encore besoin, faites-le!
Afin de réaliser un processus, plusieurs lignes peuvent être écrites. Par exemple, mettez des valeurs dans certaines variables et appelez une méthode. Dans de tels moments, bloquez ces séries de lignes pour réduire le retrait. En en faisant un bloc, vous pouvez voir que ces lignes sont une série de processus cohésifs. Vous pouvez ajouter des commentaires à l'ensemble du bloc Étant donné que les variables peuvent être définies à l'intérieur du bloc, une explosion accidentelle des variables peut être évitée.
// Ceci est un commentaire pour le bloc entier, décrivant une série de traitements dans le bloc { int a = 0; String str = "abc"; // Continuez ci-dessous. }
// Beaucoup de gens écrivent if ~ else comme suit int a = 1; if (a == 1) { // Traitement requis } else { // Un autre processus }
Décrivez-le comme suit La raison en est que vous pouvez commenter tout le reste Voir "Traitement cohésif de bloc" ci-dessus.
if (a == 1) { // Traitement requis } // Traitement en cas d'autre ⇒ Voici le commentaire de l'ensemble else else { // Un autre processus }
C'est naturel, mais je vois souvent des programmes que je n'utilise pas. Grand nombre de lignes, redondantes, difficiles à voir, ennuyeuses. Cependant, l'opérateur ternaire imbriqué n'est pas utilisé.
// Addition, utilisez l'opérateur ternaire même s'il n'y a pas d'autre → Le nombre de lignes est réduit a = (expression logique)? A = algèbre: a;
// faire ce qui suit if (expression logique) {break;}
La raison est de réduire le nombre de lignes et d'en afficher le plus possible à l'écran. Dans d'autres cas, il est interdit car la logique descendra et ce sera difficile à voir.
Parfois, je vois un programme qui est jugé par ==. Si vous regardez de près, vous pouvez devenir anémie. De plus, il réussit le test La raison pour laquelle le test est réussi est que si vous le copiez, il en sera de même.
C'est pour l'empêcher de tomber avec null. Cependant, si vous avez besoin d'un contrôle nul approprié, vous devez le vérifier dans la ligne précédente.
String str = "bbbb"; if ("aaaa" .equals ((str))) {// Remarque, "aaaa" doit être défini comme une constante // Traitement en cas de correspondance }
Boolean ne peut être que true, false (et null) et il est défini dans la classe Boolean, il n'est donc pas nécessaire de Remarque, (new Boolean (true)) == (new Boolean (true)) est false.
Boolean boolValue = Boolean.TRUE;
En plus de l'assigner à une variable, il est facile de faire des erreurs en la passant à un argument. Je m'inquiète et vérifie la méthode de l'autre partie.
class MyClass { public void method(String str) { // Quelque chose à faire } }
// faire ce qui suit MyClass myObj = new MyClass(); myObj.method((String)null);
La vérité est qu'il vaut mieux redéfinir null. Voir "Redéfinir et utiliser null ⇒ nom de classe + IS_NULL".
La raison en est que cela bogue lorsque j'essaye d'ajouter une déclaration.
Le résultat est le même même si je l'utilise, mais je ne vois pas qu'il est "traité dans l'ordre" dans le code source.
// Exemple d'utilisation de l'instruction if int a = 1; String msg; if (a == 0) { msg = "aaaa"; } else if (a == 1) { msg = "bbbb"; } // Continuez ci-dessous.
// faire ce qui suit String[] msgs = new String[] {"aaaa","bbbb"}; msg = msgs[a];
Cet exemple n'est pas apprécié, mais lors de la construction d'une machine à états, il est déroutant si vous ne le faites pas. Notez que si la valeur d'origine n'est pas l'origine zéro, vous devez rendre la séquence à deux niveaux Comme ce n'est qu'une table constante, elle est plus courte et plus facile à voir ⇒ Moins de bogues
int a = 0; if (a == 0) { // Décrivez certains traitements } else { // Pas de traitement }
Bien sûr, pas tous si les déclarations le font, mais seulement s'il y a lieu de s'interroger. Il est possible de dire qu '"il a été décidé que ce n'était pas nécessaire après avoir examiné si un traitement était nécessaire ou non".
Cela peut être difficile à comprendre car de nombreuses conditions sont liées par et dans l'instruction if. Dans un tel cas, décomposez la condition et imbriquez l'instruction if. Même si vous êtes critiqué comme "amateur", n'ayez pas peur. L'accent doit être mis sur le fait de le rendre facile à comprendre sans ajouter de bogues.
Si plusieurs conditions sont connectées par et / ou, il sera plus facile de voir si chacune est entre () et séparée.
Étant donné que le coût de création de l'objet est inutile, il peut provoquer un bogue s'il est réutilisé. Ne vous inquiétez pas, il vaut mieux créer un nouvel objet. Bien sûr, si nécessaire pour la performance, utilisez-le à nouveau.
Il devient clair que vous appelez une méthode statique, ce qui facilite la lecture de la source.
Cela sera critiqué, mais la visibilité de la source est plus importante. Certes, la performance est différente, mais dans de nombreux cas, le temps absolu est court en premier lieu. N'utilisez pas StringBuilder sauf si vous avez beaucoup de boucles. Notez que dans ma mesure, cela prend environ 10 fois lorsque StringBuilder (StringBuffer) n'est pas utilisé dans le traitement supplémentaire de String.
C'est aussi un jugement situationnel, mais il vaut mieux sortir dans une certaine mesure. Cependant, si vous en faites trop, le nombre de méthodes augmentera et vous serez confus.
Vous pouvez oublier le processus à ajouter après un nouveau, alors faites-en une habitude et ne l'oubliez pas C'est un bogue déroutant (parfois) donc pour l'empêcher
L'exception ci-dessus se produit lorsque la valeur est définie pour le nouvel objet et qu'elle ne peut pas être ajoutée en fonction des conditions.
Il peut être attrapé ou non, mais la plupart ne le seront pas. N'oublie pas enfin Même lorsque le traitement final n'est pas nécessaire, ajoutez un espace finalement vide et écrivez "aucun traitement"
Je vois que le traitement de la date et de l'heure est similaire dans diverses parties du système. Le même format est décrit à divers endroits. De plus, en particulier lors du traitement des dates, il est nécessaire d'empêcher l'entrée de bogues dus à des erreurs de temps.
C'est la même chose que de sortir en tant que DAO pour l'accès à la base de données, et un petit traitement spécial comme celui-ci devient une classe commune.
En primitif, vous devez créer une méthode pour chaque type. Vous pouvez unifier avec Number dans wrapper. Cependant, Big Decimal est également Number, ce qui est gênant
Dans une classe commune, le nom de la classe et le nom de la méthode peuvent ne pas correspondre au contenu métier. Dans ce cas, définissez une classe dérivée et donnez-lui un nom descriptif. Si vous en faites simplement trop, le nombre de classes augmentera.
L'établissement d'une classe commune au sein du projet est plutôt un facteur d'augmentation des coûts ⇒ mais il doit être établi. Le coût de la maintenance et le coût des membres saisissant les spécifications sont plus élevés. Le développement de classe commun au sein du projet est d'améliorer la qualité.Si vous ne le reconnaissez pas, vous serez frustré.
À long terme, cela entraînera également une réduction des coûts.
Recommended Posts