Avec l'essor récent de l'IA, je pense que le choix de construire avec Python pour le développement de nouveaux systèmes a augmenté. Quand il s'agit d'écrire de nouveaux services Web en Python, je pense que les principaux choix sont de fournir une API REST avec un framework tel que React ou Vue.js pour le front-end et Django ou Flask pour le back-end. Avec une configuration simple, le Django REST Framework facilite et simplifie la création d'un serveur API, mais quand cela devient un peu compliqué, cela devient rapidement chaotique si vous ne pensez pas correctement à l'architecture. ~~ Dans le cas où je suis entré, c'est déjà le chaos et le chaos. .. .. ~~ D'après mes recherches, il n'y a pas d'article sur la combinaison de Django REST Framework + Clean Architecture, donc je vais l'examiner dans cet article ainsi que dans ma propre étude et résumé de mes réflexions. ~~ C'est plutôt douloureux, alors j'aimerais vous le présenter avec le contenu résumé ici. ~~ Veuillez commenter si vous avez un bon design.
Cette fois, nous envisageons d'exclure le projet et l'application (décrit plus loin). De plus, le routage, ViewSet, ModelManager, etc. ne sont pas pris en compte.
Comme il ne s'agit que d'images et de phrases, j'ai essayé d'implémenter un échantillon. Un exemple de code peut être trouvé ici [https://github.com/ryoutoku/django_rest_clean_architecture). Sur la base du modèle de didacticiel Django, j'essaierai d'implémenter uniquement Question POST. (Cependant, comme je ne pouvais pas trop penser à la logique métier, c'est juste une implémentation qui rend le traitement POST inutilement redondant.)
Django lui-même est un framework basé sur l'idée qu'il y a plusieurs applications dans un projet et MVT (Model
, View
, Template
).
Dans le Framework Django REST, il n'y a pas de Template
et plus Serializer
.
Vous trouverez ci-dessous un diagramme de l'architecture et des rôles du Framework Django REST.
Pour le traitement CRUD pour un modèle
(1 table de base de données), fondamentalement vue
-- sérialiseur
-- model
est 1 à 1 à 1, et il peut être fait simplement.
Pour les services Web de niveau métier, lorsque l'API REST est exécutée, le traitement logique est effectué en fonction de certaines connaissances, règles et jugements métier, il est donc rare que seul le traitement CRUD d'une table soit effectué. Cependant, si vous démarrez l'implémentation sans considérer l'architecture en profondeur, l'architecture fournie par le Django REST Framework conduira au chaos. .. ..
Pour moi, les deux points suivants sont de gros problèmes qui ont tendance à être chaotiques. N'est-ce pas fondamentalement un cadre qui brise facilement le principe de la responsabilité unique? Je sens ça.
views
a tendance à être compliqué (il a tendance à être Fat Contoller)C'est un problème appelé Fat Controller, dans lequel la logique est écrite dans les vues
.
C'est un problème qui a tendance à se produire lorsqu'un débutant ou quelqu'un qui ne s'intéresse pas à l'architecture le fait.
Dans Django REST Framework, s'il est simple, il n'y a presque pas d'implémentation du traitement CRUD comme indiqué ci-dessous.
models.py
from django.db import models
class Question(models.Model):
#Offrir ORM
question_text = models.CharField(max_length=10)
pub_date = models.DateTimeField('date published')
serialzers.py
from .models import Question
from rest_framework import serializers
class QuestionSerializer(serializers.ModelSerializer):
# data <->Fournit une conversion de modèle
class Meta:
model = Question
fields = '__all__'
# data <->modèle Définit le modèle et le champ à convertir
views.py
from rest_framework import viewsets
from .models import Question
from .serializers import QuestionSerializer
class QuestionViewSet(viewsets.ModelViewSet):
#API REST I/Offre O
queryset = Question.objects.all()
serializer_class = QuestionSerializer
#Parce que la source d'héritage ModelViewSet définit une fonction qui est une API pour le traitement CRUD.
#Pas besoin de créer une méthode
Le traitement CRUD est fourni et masqué du côté de Django REST Framework.
Par conséquent, par exemple, si vous devez incorporer une certaine logique lors de la sauvegarde des données (POST), vous pouvez facilement l'écrire dans views-> "Ajouter à vues
(contrôleur) pour le moment ". N'est-ce pas souvent le cas que vous écrivez diverses choses en .py?
Si vous n'écrivez pas une nouvelle classe au lieu de l'écrire solidement, cela vous fera devenir un Fat Controller.
Puisque Serializer fournit la validation, vous vous demanderez où mettre en œuvre la validation (pas au niveau des connaissances métier) comme les limites supérieure et inférieure des valeurs et le format des chaînes de caractères.
Si vous mettez la logique de la manière dont elle est implémentée dans les sérialiseurs
parce que la validation est fournie, cela placera seliarizers
sur plusieurs responsabilités.
Quelle est la validation des "sérialiseurs" lorsqu'ils sont implémentés dans "models"? Cela deviendra.
De plus, si vous développez avec un grand nombre de personnes, la logique sera dispersée à moins que vous ne l'implémentiez avec une idée unifiée. .. ..
Si vous ne pensez pas à quoi mettre en œuvre et où, cela peut provoquer le chaos.
Je pense que la raison pour laquelle Serializer a tendance à être chaotique est qu'il fournit trop de fonctions (trop bonnes). Plus précisément, je me demande si la cause est la suivante.
-Serializer.save ()
enregistre l'enregistrement model
correspondant (en fonction de la classe Serializer héritée)
modèle
ou sérialiseur
--Serializer a une fonction de validation et la validation peut être personnalisée.
-> Je veux mettre des connaissances métier dans serializer.validation ()
(car ça s'appelle validation)J'ai googlé "django rest framework logic" et il est sorti en premier cette page, Il est écrit que la logique est collectée dans les «sérialiseurs». Cependant, il y a un problème avec le test. Cette personne est écrite comme étant en «vues», mais je pense que la logique métier est susceptible d'être dispersée. .. .. ..
Ci-dessous, un schéma de la correspondance entre le Framework Django REST et Clean Architecture que j'interprète. La gauche est la composition originale, la droite est la [figure habituelle] de Clean Architecture (https://blog.cleancoder.com/uncle-bob/images/2012-08-13-the-clean-architecture/CleanArchitecture.jpg) J'ai essayé de le cartographier. La gauche est la référence et la droite est le mappage.
En regardant cela, il n'y a pas de règle métier xxx correspondante. .. ..
Sur la base de ce qui précède, nous l'avons conçu comme suit. Ou plutôt, j'ai probablement fait référence à ici.
En gros, je l'ai conçu avec la politique suivante. De toute évidence, la logique de domaine ne doit pas être écrite dans les vues, les sérialiseurs et les modèles. Inversement, pour ceux qui n'incluent pas la logique de domaine, il est supposé être utilisé selon le Framework Django REST.
Le comportement lors de la frappe de l'API REST est décrit ci-dessous (certains ne sont pas implémentés).
--Lors de l'exécution de la requête (GET)
--Utilisez les fonctions fournies par Django REST Framework telles quelles
--Lors de l'extraction de données à partir de ressources autres que Django, définissez-les avec SerializerMethodField
etc. du côté serializer
.
--Dans validate ()
of serializer
, validez la valeur en utilisant ʻAggregate et
DomainObject`.
--Lors de l'exécution de la commande (POST / PUT / PATCH / DELETE): avec la logique métier ver
views
transmet dict
des données du sérialiseur
à ʻapplication_services` comme argument crée et traite ʻAggregate
basé sur l'argument dict
.
--Utilisez ʻIXXXReader pour générer ʻAggregate
à partir des données DBdict
, générez ʻAggregate, passez-le à ʻIXXXWriter
et enregistrez-le.dict
tenant compte de la réponse en vues
serializer
pour la réponse basée sur dict
obtenu à partir de ʻapplication_services`Voici un résumé de mes réflexions lors de la recherche et de la conception.
str
pour data
et de datetime
pour validated_data
.DomainObject
, ou le rendre plus simple.
--Il est préférable d'utiliser NamedTuple
ou de dicter la propriété pour la rendre plus facile à créer et à utiliser.Si vous souhaitez créer un serveur API (ou concevoir un URI), j'ai pensé qu'il serait préférable d'utiliser correctement les API GraphQL et REST avec la politique suivante.
--Fourni par GraphQL pour la requête
Je suis sûr sur le site actuel "C'est plus simple et plus facile à comprendre si vous insérez la logique dans des" vues "(1 méthode a plus de 200 lignes de logique implémentées)" "Si vous faites un cours en vain, la performance sera ... (Il semble que la performance ne soit pas mesurée)" Ah ... je ne sais pas ...
https://medium.com/@amarbasic4/django-rest-framework-where-to-put-business-logic-82e71c339022 https://isseisuzuki.com/it/django-rest-framework-concept/ https://qiita.com/MinoDriven/items/3c7db287e2c66f36589a https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html https://blog.tai2.net/the_clean_architecture.html
Recommended Posts