[JAVA] [Kotlin] Un exemple de traitement utilisant Enum

en premier

J'ai beaucoup utilisé Enum lors de l'écriture de code, je vais donc résumer les exemples réels que j'ai utilisés.

Le code est écrit en Kotlin. Bien que la méthode de description soit différente, je pense qu'elle peut être implémentée en Java avec le même mécanisme. (Peut-être que cela peut être fait dans d'autres langues)

Valeur de code ⇔ processus de conversion de nom

S'il existe une spécification telle que "Gérer avec la valeur de code (01 etc.) sur les données, mais que vous souhaitez l'afficher avec le nom lors de son affichage à l'écran", il est nécessaire de convertir la valeur de code en nom et le nom en valeur de code.

Dans ce qui suit, nous allons lister le cas de l'utilisation du branchement conditionnel simple et la méthode d'implémentation utilisant Enum.

Comment utiliser le branchement conditionnel

Voici quelques codes auxquels je peux penser:

    //Convertir le code en nom
    fun convert(code : String) : String {

        if ("01" == code) {
            return "Nom 1"
        } else if ("02" == code) {
            return "Nom 2"
        }

        //Après cela, des branches conditionnelles sont ajoutées pour le nombre de valeurs de code.

        //Si non applicable, retournez-le tel quel
        //Il y a des spécifications ici.
        return code
    }

La branche conditionnelle peut être une instruction switch ou une instruction when. Puisque ce qui précède est le processus de conversion de valeur de code, il est également nécessaire de créer le processus de conversion de valeur de code.

Comment utiliser Enum

Il peut être implémenté à l'aide du branchement conditionnel, mais deux processus doivent être modifiés chaque fois qu'une valeur de code est modifiée ou ajoutée. C'est tout simplement ennuyeux.

La méthode utilisant Enum utilise le fait qu'Enum est une classe qui peut définir des variables et des méthodes ainsi qu'énumérer des constantes, et implémente de manière à ne pas écrire autant de branches conditionnelles que le nombre de codes.

En mettant en œuvre de cette manière, des branches conditionnelles supplémentaires peuvent être supprimées, et même s'il y a des changements ou des ajouts, seule la définition de Enum peut être modifiée.


enum class Test(val code : String, val value : String) {

    //S'il y a un changement dans la valeur du code, corrigez-le ici
    KUBUN1("01", "Nom 1"),
    KUBUN2("02", "Nom 2"),
    KUBUN3("03", "Nom 3");

    //Définition de la méthode statique en Java
    companion object {
        fun toValue(code : String) : String {
            //S'il y en a une qui correspond à l'énumération Enum, renvoyez-la
            for (item in enumValues<Test>()) {
                if (item.code == code) {
                    return item.value
                }
            }
            
            //S'il n'y a pas d'élément applicable, renvoyez l'entrée telle quelle
            return code
        }

        fun toCode(value : String) : String {
            //S'il y en a une qui correspond à l'énumération Enum, renvoyez-la
            for (item in enumValues<Test>()) {
                if (item.value == value) {
                    return item.code
                }
            }

            //S'il n'y a pas d'élément applicable, renvoyez l'entrée telle quelle
            return value
        }
    }
}

Vous pouvez utiliser le processus de conversion d'une manière comme Test.toValue (n'importe quelle valeur).

Même dans l'exemple ci-dessus, si une modification est apportée, la définition de classe sera modifiée, mais la différence par rapport à l'exemple utilisant le branchement conditionnel est que ** traitement ** et ** données ** sont séparés. C'est dedans. Dans l'exemple de branchement conditionnel, les données et le traitement sont intégrés, donc si les données sont modifiées, le traitement doit également être modifié, mais dans l'exemple Enum, seules les données sont modifiées et il n'est pas nécessaire de modifier le traitement. ..

Pour séparer plus de données

Si vous ne voulez pas avoir de données dans la classe de toute façon, vous pouvez écrire la définition dans un fichier externe et la lire pour construire Enum. (Essayez Json)

Ou enregistrez-le dans la base de données. En premier lieu, si la spécification doit gérer les valeurs de code lors du traitement, je pense que les données sont souvent la valeur à enregistrer dans la base de données, ce qui est plus réaliste.

Celles-ci affecteront les performances en raison de l'augmentation du nombre d'E / S de fichiers et d'accès à la base de données, il peut donc être préférable de prendre des mesures telles qu'une tonne unique. Dans le même temps, thread safe.

Serpentin

Si vous souhaitez écrire la classe Enum uniquement pour les données et écrire le traitement séparément, vous pouvez l'implémenter à l'aide de l'interface.


interface ITest {
    fun code() : String
    fun value() : String
}


enum class Test(val code : String, val value : String) : ITest {

    KUBUN1("01", "Nom 1"),
    KUBUN2("02", "Nom 2"),
    KUBUN3("03", "Nom 3");

    override fun code(): String {
        return code
    }

    override fun value(): String {
        return value
    }

    companion object {
        //Java est OK si le type de tableau est utilisé comme interface
        //Kotlin est une classe, donc ça demande un petit effort
        val VALUE : Array<ITest> = Arrays.copyOf(values(), values().size)
    }
}


class Hoge {
    companion object {
        fun toValue(items : Array<ITest>, code: String): String {
            //S'il y en a une qui correspond à l'énumération Enum, renvoyez-la
            for (item in items) {
                if (item.code() == code) {
                    return item.value()
                }
            }

            //S'il n'y a pas d'élément applicable, renvoyez l'entrée telle quelle
            return code
        }

        fun toCode(items : Array<ITest>, value: String): String {
            //S'il y en a une qui correspond à l'énumération Enum, renvoyez-la
            for (item in items) {
                if (item.value() == value) {
                    return item.code()
                }
            }

            //S'il n'y a pas d'élément applicable, renvoyez l'entrée telle quelle
            return value
        }
    }
}

fun main(args: Array<String>) {
    //Le nom 2 sort
    println(Hoge.toValue(Test.VALUE, "02"))
}

Le processus de conversion d'origine reçoit l'entrée à l'interface et le processus à l'intérieur appelle le processus d'implémentation de l'interface.

La raison de l'utilisation de l'interface est que si vous définissez plusieurs Enums mais que vous avez le même objectif, vous pouvez réaliser le processus de conversion avec une seule méthode en utilisant l'interface. Non requis si vous ne souhaitez créer qu'un seul Enum.

Traitement des jugements en combinant des éléments arbitraires

Il existe des éléments appelés statut et statut de traitement, et si vous souhaitez réaliser un traitement qui renvoie un booléen en combinant les éléments ci-dessus, vous devez vérifier chaque élément et renvoyer le résultat.

Les combinaisons lorsque la colonne est le statut de traitement et la ligne est le statut sont indiquées ci-dessous. Considérez-le comme renvoyant vrai pour ○ et faux pour ×.

01 02 03
1 × ×
2 × × ×
3 ×

Dans ce qui suit, nous listerons le traitement utilisant le branchement conditionnel et la méthode d'implémentation utilisant Enum.

Comment utiliser le branchement conditionnel

Il existe les méthodes suivantes. Dans ce processus, seules les conditions vraies sont extraites et les autres sont définies comme fausses et levées en tant que conditions. Vous pouvez décrire toutes les branches conditionnelles.


    //Vérifier l'entrée et renvoyer le résultat
    fun validate(status : String, processStatus: String) : Boolean {

        if (status == "1" && processStatus == "01") {
            return true
        } else if (status == "3" && processStatus == "01") {
            return true
        } else if (status == "3" && processStatus == "03") {
            return true
        } else {
            return false
        }
    }

Comment utiliser Enum

La mauvaise chose à propos de ** comment utiliser le branchement conditionnel ** est qu'il n'est pas clair ce que signifie chaque valeur utilisée dans le branchement conditionnel. Dans la plupart des cas, ce qui est représenté par une valeur de code doit avoir une certaine signification.

L'état de traitement "01" est en attente de traitement, "02" est traité. L'état "1" est normal, "2" est une erreur. Par exemple, cela devrait signifier quelque chose comme ceci, mais cette branche conditionnelle ne peut pas le lire.

Dans de tels cas, la méthode de définition des constantes et de signification est prise. Si le nombre de constantes est grand, cela devient compliqué, nous utilisons donc Enum pour résumer.

Utilisons maintenant Enum pour créer une constante et donner un sens à la branche conditionnelle.

"Attendez, était-ce le mérite d'utiliser Enum pour rendre le branchement conditionnel significatif?"

Oui c'est vrai. Si vous voulez du sens, vous pouvez utiliser une constante ou Enum. (Si vous voulez créer une unité significative avec des constantes comme conception, je pense que Enum est bon)

Si vous voulez utiliser le fait qu'Enum est une classe, essayez de l'utiliser un peu plus comme une classe.

Dans le traitement suivant, groupez par état (ligne) et créez un Enum qui renvoie un booléen basé sur la combinaison de l'état et de l'état du traitement. Le concept de traitement est le même que pour la ** méthode utilisant le branchement conditionnel **.


enum class StatusEnum {

    //Définir Enum dans l'état
    //Vrai lorsque l'état est 1 et l'état de traitement est 01
    STATUS_1 {
        override fun validate(status: String, processStatus: String): Boolean {
            return status == "1" && processStatus == "01"
        }
    },
    //État: 2 est toujours faux
    STATUS_2 {
        override fun validate(status: String, processStatus: String): Boolean {
            return false
        }
    },
    //Vrai lorsque l'état est 3 et que l'état de traitement est différent de 02
    STATUS_3 {
        override fun validate(status: String, processStatus: String): Boolean {
            return status == "3" && processStatus != "02"
        }
    };

    abstract fun validate(status : String, processStatus : String) : Boolean

    //Vérifiez les informations transmises ici
    companion object {
        fun isStatusValidate(status : String, processStatus : String) : Boolean {
            for (item in values()) {
                val result = item.validate(status, processStatus)
                if (result) {
                    return result
                }
            }
            return false
        }
    }
}

Enum vérifie l'état dont il est responsable tout en le résumant dans l'état et en donnant un sens au littéral de caractère lui-même, et l'hypothèse isStatusValidate () utilisée de l'extérieur appelle le traitement d'Enum et renvoie le résultat. Je vais. (Si vous voulez avoir une signification, la signification de l'état lui-même devrait être le nom de la variable, mais ici c'est le nom tel qu'il est par exemple)

Par conséquent, si le statut augmente, la définition de Enum doit être augmentée et si le statut de traitement change, seul le traitement de retour de Enum concerné doit être modifié. Vous n'avez pas à encombrer de longues instructions conditionnelles.

Serpentin

Dans l'exemple ci-dessus, le processus de vérification de la valeur d'entrée dans le processus Enum est décrit, mais comme le groupe est créé dans l'état, j'ai pensé qu'il serait plus facile de transmettre la signification au groupe s'il s'agissait d'une variable. C'était.

Voici un exemple de passage de l'état en entrée lors de la génération d'Enum.


enum class StatusEnum(val status : String) {

    //Définir Enum dans l'état
    //Vrai lorsque l'état est 1 et l'état de traitement est 01
    STATUS_1("1") {
        override fun validate(status: String, processStatus: String): Boolean {
            return this.status == status && processStatus == "01"
        }
    },
    //État: 2 est toujours faux
    STATUS_2("2") {
        override fun validate(status: String, processStatus: String): Boolean {
            return false
        }
    },
    //Vrai lorsque l'état est 3 et que l'état de traitement est différent de 02
    STATUS_3("3") {
        override fun validate(status: String, processStatus: String): Boolean {
            return this.status == status && processStatus != "02"
        }
    };

    abstract fun validate(status : String, processStatus : String) : Boolean

    companion object {
        fun isStatusValidate(status : String, processStatus : String) : Boolean {
            for (item in values()) {
                val result = item.validate(status, processStatus)
                if (result) {
                    return result
                }
            }
            return false
        }
    }
}

Hmm. C'est comme un serpent.

Si le nom de la variable Enum utilise ** la signification de l'état ** comme nom, "1" ou "2" est défini comme la valeur spécifique du nom et si le contrôle d'état est le même que lui-même. Cela ressemble à, donc c'est plus facile à lire ... mais j'ai l'impression que peu importe à qui vous venez.

À la fin

Il s'avère que l'utilisation du fait qu'Enum est une classe permet non seulement une simple énumération de constantes, mais également le traitement et la définition de propriété.

Cela conduit à la suppression des instructions conditionnelles inutiles et à la simplification de la conception (réduction du nombre de lignes de code à écrire, etc.), j'ai donc pensé qu'il valait la peine de considérer diverses choses.

Recommended Posts

[Kotlin] Un exemple de traitement utilisant Enum
Exemple d'utilisation de vue.config.js
Exemple de paramètres utilisant where
Exemple d'utilisation d'une classe abstraite
Exemple d'utilisation d'ArAutoValueConverter (conversion de type de champ)
Un exemple où il est plus rapide d'utiliser l'addition que d'utiliser StringBuilder (Java)
Exemple d'utilisation de Java Enum
Exemple d'implémentation d'un système de traitement LISP simple (version Java)
Résumé de l'utilisation de FragmentArgs
Exemple d'implémentation d'un système de traitement LISP simple (version Ruby)
[Java] [Kotlin] Appeler valueOf et les valeurs de Enum de manière générique
Résumé de l'utilisation de DBFlow
[Enum] Utilisez des rails enum pour améliorer la lisibilité des données
Exécution du traitement initial à l'aide de Spring Boot Command Line Runner
Processus de nettoyage des phrases japonaises
Résumé de l'utilisation de ButterKnife
Traitement des données avec Apache Flink
[Swift] Traitement asynchrone à l'aide de PromiseKit
[Traitement] Essayez d'utiliser GT Force.
Traitement de la sortie CSV avec Super-CSV
Résumé du traitement des erreurs Java
Implémentation de HashMap avec kotlin
[Rails] Implémentation de la fonction coupon (avec fonction de suppression automatique par traitement par lots)
Exemple d'implémentation d'un système de traitement LISP simple [Résumé de chaque version linguistique]