L'histoire du retour au front pour la première fois en 5 ans et de la refactorisation de Python Django

Contexte

Je suis dans la startup depuis l'année dernière et je développe avec le framework Python Django. Il y avait un développement vierge pendant près de cinq ans, alors j'ai décidé d'être optimiste, "Est-ce le développement d'aujourd'hui?" Cependant, il était plein de divers anti-motifs et points de plongée.

L'ancien responsable et le responsable précédent ont cessé et l'attachement a été inversé. En regardant le code laissé derrière, je ne peux pas m'empêcher d'y penser.

Dans de telles circonstances, je voudrais résumer l'histoire du refactoring et l'histoire du refactoring à partir de maintenant.

Le problème qui était blâmé

Il semble que cela ne s'arrêtera pas quand je commencerai à parler, mais il y avait deux choses décevantes en termes d'architecture.

Voir trop intelligent

Il semble que ce soit une application simple dont la vue ne récupère que les données créées à l'origine par le traitement par lots. Cependant, avec l'ajout de fonctions, divers calculs sont désormais effectués dans la vue.

Logique encombrée

Il semble que la personne précédente ait essayé de faire quelque chose, mais la logique est restée dans la vue et le modèle avait une logique. Vous pouvez générer des références circulaires dans deux packages différents. Je n'ai pas confirmé l'opération. Ça a été terrible.

Le problème fondamental est ...

J'ai mis de côté le fait que je n'avais pas assez de temps, ~~ le responsable était stupide ~~, et cela dépend de la situation et des gens.

En premier lieu, Django suppose une configuration simple avec une table et un modèle 1: 1. C'est un peu différent de la signification originale, mais c'est probablement le modèle Active Record.

Cette configuration devient problématique à mesure que l'application devient plus complexe.

À mesure que la fonctionnalité devient plus complexe, la table change. Il peut ne pas correspondre au modèle que vous attendiez à l'origine.

Avec Django, vous avez tendance à appeler le modèle directement depuis la vue.

Lorsque vous combinez des informations provenant de plusieurs tables, vous avez tendance à écrire une logique dans la vue. Si vous faites des calculs compliqués, il sera difficile de comprendre où se situe la responsabilité, en vous demandant: "Quoi? Ce modèle est-il responsable?"

Model-View-Controller est un modèle de couche de présentation en premier lieu. Il semble que le modèle soit mélangé avec le modèle architectural de la source de données, ce qui prête à confusion. (Je pense que je ne comprends tout simplement pas)

Solution

Je suis retourné à l'essentiel et j'ai commencé par superposer. À ce moment-là, j'ai fait référence à la conception axée sur le domaine et au modèle d'architecture d'entreprise (bien qu'il ait une mauvaise réputation).

Personnellement, j'en avais marre du contenu du modèle d'architecture d'entreprise.

http://www.amazon.co.jp/dp/4798121967 http://www.amazon.co.jp/dp/4798105538

Révision: couche d'application de base

Il y a quelques motifs, mais il était facile de comprendre comment les diviser en 4 couches.

Encore une fois, ce qui rendait Django personnellement déroutant, c'est qu'il semblait que le modèle de couche de présentation, la couche de domaine et la couche de données étaient tous en un. C'est devenu une clé pour diviser cette zone.

Introduction de la couche de service

Modifié pour fournir un service pour une vue. Je ne veux pas que les paramètres de méthode soient compliqués, je les laisse donc gérer les paramètres de type objet de transfert de données.

Le service est également divisé en deux types.

La première consiste à gérer le CRUD de base. La convention de dénomination est également XxxService.

L'autre consiste à combiner plusieurs objets pour effectuer des calculs et des traitements complexes. La convention de dénomination est également XxxEngine.

Je n'ai pas bien compris même si j'ai lu diverses explications, alors je me suis référé au code suivant. http://www.infoq.com/jp/news/2015/04/ddd-trading-example https://github.com/archfirst/bullsfirst-server-java

Il est également inefficace de créer une instance du service à chaque fois, donc je l'ai fait Singleton.

http://code.activestate.com/recipes/579090-yet-another-singleton-pattern-in-python-using-clas/

C'est un problème futur.

Il y avait des choses similaires dans XxxEngine. C'est une brume qui vous donne une meilleure vue si vous la séparez avec le modèle Stratégie.

Manipulation des modèles

J'ai décidé de considérer le modèle de Django comme une couche de données.

Introduction de la couche de domaine

Dans le futur, je pense introduire une couche de domaine. Implémentez la logique de domaine dans une classe qui hérite du modèle de Django.

Autrefois, lors de la conversion d'une table en objet, il était mappé vers POJO (Plain Old Java Object). Pour implémenter la logique en tant que modèle de domaine, une classe héritant de POJO a été utilisée. Avec cela comme référence, je pense hériter de POMO (mon mot inventé w: Plain Old Model Object) et en faire un modèle de domaine.

Résumé

J'ai toujours l'impression que c'est subtil, mais la situation actuelle est comme ça.

Quand j'ai vu l'histoire de l'introduction de la couche service dans Rails, j'ai pensé "Il y a des gens qui pensent la même chose", alors j'ai résumé ce que je pensais / correspondais dans Django.

Cependant, ce qui m'inquiétait cette fois, c'était le problème dont on parlait dans le modèle d'application d'entreprise. De nos jours, il y a beaucoup de choses que le framework cache et dont il n'est pas conscient. Mais quand j'essayais de repousser les limites du cadre, j'ai pensé qu'il était important de connaître les bases.

Recommended Posts

L'histoire du retour au front pour la première fois en 5 ans et de la refactorisation de Python Django
Résumé des points d'achoppement à Django pour la première fois
Vérifiez le temps de traitement et le nombre d'appels pour chaque processus avec python (cProfile)
Google recherche la chaîne sur la dernière ligne du fichier en Python
L'histoire de Python et l'histoire de NaN
L'histoire de la création d'un «espace de discussion sur l'esprit et le temps» exclusivement pour les ingénieurs de l'entreprise
Déterminez le format de la date et de l'heure avec Python et convertissez-le en Unixtime
[Python] Comment obtenir le premier et le dernier jour du mois
Mettre le processus en veille pendant un certain temps (secondes) ou plus en Python
L'histoire de la sortie d'un outil de vérification de texte créé par Python sur GitHub x CircleCI pour la première fois
[Python] Le rôle de l'astérisque devant la variable. Divisez la valeur d'entrée et affectez-la à une variable
Un débutant en Python a d'abord essayé une analyse rapide et facile des données météorologiques des 10 dernières années.
Comment obtenir la différence de date et d'heure en secondes avec Python
Pour la première fois dans Numpy, je vais le mettre à jour de temps en temps
Une note utile lors de l'utilisation de Python après une longue période
L'histoire de la recherche d'un magasin BOT (AI LINE BOT) pour Go To EAT dans la préfecture de Chiba (1)
Une histoire d'essayer d'améliorer le processus de test d'un système vieux de 20 ans écrit en C
Comment utiliser MkDocs pour la première fois
L'histoire selon laquelle le coût d'apprentissage de Python est faible
J'ai essayé la programmation python pour la première fois.
Traitement d'image? L'histoire du démarrage de Python pour
L'histoire de la lecture des données HSPICE en Python
L'histoire de l'affichage des fichiers multimédias dans Django
Pour représenter la date, l'heure, l'heure et les secondes en Python
Histoire de base de l'héritage en Python (pour les débutants)
Essayez de publier sur Qiita pour la première fois
Différentes façons de lire la dernière ligne d'un fichier csv en Python
Analyse des données en Python Résumé des sources que les débutants devraient d'abord consulter
Comment compter le nombre d'éléments dans Django et sortir dans le modèle
Je veux obtenir le nom du fichier, le numéro de ligne et le nom de la fonction dans Python 3.4
Histoire de faire une recherche de magasin BOT (AI LINE BOT) pour Go To EAT dans la préfecture de Chiba (2) [Présentation]
[Super facile! ] Comment afficher le contenu des dictionnaires et des listes incluant le japonais en Python
[Astuces] Problèmes et solutions dans le développement de python + kivy
L'histoire du retour au front pour la première fois en 5 ans et de la refactorisation de Python Django
Comptez bien le nombre de caractères thaïlandais et arabes en Python
Remarque: obtenez les premier et dernier éléments de Python OrderedDict de manière non destructive
[Python] Comment obtenir le premier et le dernier jour du mois
Obtenez le titre et la date de livraison de Yahoo! News en Python
Convertir la date et l'heure zonées en temps Unixtime dans Python2.7
Le mur lors du passage du service Django de Python 2.7 à la série Python 3
Comment obtenir le nombre de chiffres en Python
Ce que je suis entré dans Python pour la première fois
J'ai essayé Python sur Mac pour la première fois.
L'histoire du serveur Web et du DAG d'Airflow, dont le chargement prend beaucoup de temps
La première étape de l'apprentissage automatique ~ Pour ceux qui veulent essayer l'implémentation avec python ~
[Python] Mesure et affiche le temps nécessaire au traitement
Enregistrer une tâche dans cron pour la première fois
Construisez un serveur API pour vérifier le fonctionnement de l'implémentation frontale avec python3 et Flask
J'ai essayé python pour la première fois avec heroku
L'histoire de FileNotFound en Python open () mode = 'w'
[python] Calcul des mois et des années de différence de date / heure
Je souhaite créer une base de données de déjeuner [EP1-4] Django pour la première fois
La première étape pour ceux qui sont amateurs de statistiques mais qui souhaitent implémenter des modèles d'apprentissage automatique en Python
Sortie de la table spécifiée de la base de données Oracle en Python vers Excel pour chaque fichier
Je voulais juste extraire les données de la date et de l'heure souhaitées avec Django
Une histoire sur la tentative d'introduire Linter au milieu d'un projet Python (Flask)
Pour faire l'équivalent de Ruby ObjectSpace._id2ref en Python
Je suis à Singapour en ce moment Une histoire sur la création d'un LineBot et la volonté de faire un travail mémorable
Procédure pour changer le nom de la table et le nom de la colonne du modèle Django en même temps
[Super facile! ] Comment afficher le contenu des dictionnaires et des listes incluant le japonais en Python
De zéro connaissance de Python à la création d'IA en première année du collège
Quel type d'environnement les personnes qui apprennent Python pour la première fois devraient-elles créer?
Un moyen simple de visualiser le temps pris en Python et un moyen plus intelligent de l'améliorer
Conseils aux débutants en Python pour utiliser l'exemple Scikit-image pour eux-mêmes 8 Mesure du temps de traitement et profileur
Vérifiez le fonctionnement de Python pour .NET dans chaque environnement
L'histoire de l'introduction de Jedi (package de complétion automatique de python) dans emacs