Remarques rendus : Django 2020 2021 revue de mi projet - HE-Arc/slides-devweb GitHub Wiki

Intro

Bonjour à tous, j'ai donc comme convenu parcouru tous vos projets. En les parcourant j'ai décidé de regrouper toutes les infos pertinentes et de les partagés à vous tous. Le but est de vous donner quelques pistes qui permettront d'améliorer vos projets ou de corriger certaines choses. Je vous partagerais des "good practices", mais c'est à vous de voir lesquelles peuvent être appliqués à votre projet.

Remarques / suggestions / conseils

Django

Séparer les fichiers pour plus de clarté

De base Django vous fournit un fichier models, views, (serializers, viewsets pour les utilisateurs du Django REST Framework), etc. Ces fichiers peuvent être séparés en plusieurs afin de regrouper les éléments par fonctionnalités ou autrement. Mais évitez de mettre toutes les classes dans un seul fichier comme c'est le cas chez la quasi totalité d'entre vous. On vous apprend continuellement dans le dev à séparer correctement votre code en classes/méthodes/autres et là tout à coup Django fait autrement.

Ce n'est pas entièrement votre faute, car Django vous propose cette architecture de base, il pour que vous puissiez rapidement commencer à codez. Mais plus votre projet grossit, plus il devient intéressant de séparer votre code pour qu'il soit plus clair et mieux architecturé. D'ailleurs dans Django il est également intéressant d'utiliser la notion d'apps. La plupart d'entre vous avez fait une seule app, peut être que vous pourriez séparer certaines choses dans 2 ou plus d'apps. Je vous laisse le soin de voir si ces propositions peuvent être intéressantes pour votre projet.

Si vous souhaitez séparer vos fichiers, voici une ressource qui pourrait vous aider : how-to-split-views-into-multiple-files.html

Linter et Formatter

Certains groupes s'appliquent pour appliquer une convention commune à tous les devs, d'autres groupes laisse cela un peu de côté. Qu'est se que vous diriez si je vous disais qu'il est possible d'ajouter des packages à votre projets / des extensions à votre IDE (VSCode dans notre cas) pour que la plus part de ces conventions soient appliqués automatiquement par tous les devs :)

Il y a plusieurs normes / standards, je vous donne ici se que je trouve pertinent, mais libre à vous de voir si il y a plus pertinent pour votre projet.

  • Django : Package pylint et pylint-django, extension vscode python et ensuite configurez le tout dans VSCode pour que le formatage soit appliqué à chaque fois que vous sauvegardez votre code. Dans certains cas le package autopep8 peut vous être utile.
  • VueJS : extension vscode Vuetur et Prettier, ESLint et ensuite configurez le tout dans VSCode pour que le formatage soit appliqué à chaque fois que vous sauvegardez votre code.

Django REST Framework

Ici je vais parler de certaines choses que j'ai pu voir concernant le package Django REST Framework que pas mal d'entre vous ont utilisés pour faire leur APIs.

Permissions

Petit point, j'ai vu quelques groupes utilisés les permissions, je vous met ici un stackoverflow pour vous expliquer la différence entre has_permission et has_object_permission. Certains groupes pourraient améliorer cet aspect : whats-the-differences-between-has-object-permission-and-has-permission-in-drfp

VueJS

axios + VueX Store

Ne faîtes pas vos call axios dans vos fichiers .vue. Créez des actions dans vos stores. Cela permet de mieux séparer les logiques et permet d'éventuellement réutiliser des actions du store dans différentes views (DRY).

async/await et try/catch

Beaucoup d'entre vous utilisez axios pour vos requêtes async. Essayez d'utiliser la technique du async/await qui rend le code bien plus lisible. Le code asynchrone est écrit comme si il était synchrone pour améliorer sa lisibilité. Exemple :

Version à éviter

login() {
  axios.get('url')
    .then(response => {
      console.log(response);

      axios.get('url2')
        .then(response2 => {
          console.log(response2);
        })
      .catch(error2 => {
        console.log(error2);
      })
    })
    .catch(error => {
      console.log(error);
    })
},

Version à préférer

async login() {
  try {
    const response = await axios.get('url');
    console.log(response);

    const response2 = await axios.get('url2');
    console.log(response2);
  } catch (error) {
    console.log(error);
  }
},

Général

.gitignore

Je vois pas mal de groupe générer ses gitignore à la main. Si jamais il existe pas mal d'outils bien pratique, pour n'en citer qu'un gitignore.io

.env

Je n'ai pas vu beaucoup de .env dans vos projets, pourtant c'est une bonne pratique autant frontend que backend. Il s'agit d'un fichier se nommant .env qui n'est PAS push sur git et il vous permet d'y mettre des variables contenant des mots de passes ou d'autres valeurs qui ne devrait pas être push. Vous pourriez également y mettre des variables contenant une config pour votre setup local et une autre config pour votre setup en prod. Un fichier .env.example est souvent créé avec des valeurs par défaut que les gens doivent ensuite copier/coller et renommer en .env pour avoir leur config. Pour chaque Framework l'utilisation de ce fichier est différent et il existe une multitude de méthode pour mettre cela en place. Je vous résume mon expérience ici :

  • Django : installer django-environ
  • VueJS : Cela dépend de l'intégration de votre VueJS dans votre projet, allez checker ici pour voir si cela pourrait vous aider. Sinon trouvez une solution approprié à vos besoins.

if/else vs if/return

Préféré if/return plutôt que if/else quand cela est possible. Pour illustrer, voici 2 versions d'un code similaire écrit de 2 manières différentes. La version 1 est la version classique d'écrire ce code. La version 2 est identique d'un point de vue performance, par contre elle ajoute beaucoup de lisibilité ! Essayez de préférer la version 2 quand cela est possible.

Version 1 avec if/else

def try_signup(request):
    if request.user.is_authenticated:
        return JsonResponse({'error': True, 'msg': 'already_connected'})
    if request.method == 'POST':
        if 'username' in request.POST and 'password' in request.POST:
            username = request.POST['username']
            password = request.POST['password']
            if len(username) >= 3 and len(password) >= 3:
                doesExist = User.objects.filter(username=username).exists()
                if not doesExist:
                    user = User.objects.create_user(username, password=password)
                    # user = authenticate(username=username, password=password)
                    auth_login(request, user)
                    return JsonResponse({'error': False, 'msg': 'signed'})
                else:
                    return JsonResponse({'error': True, 'msg': 'user_already_exist'})
            else:
                return JsonResponse({'error': True, 'msg': 'invalid_data'})
        else:
            return JsonResponse({'error': True, 'msg': 'invalid_post'})
    else:
        return JsonResponse({'error': True, 'msg': 'invalid_request'})

Version 2 avec if/return

def try_signup(request):
    if request.user.is_authenticated:
        return JsonResponse({'error': True, 'msg': 'already_connected'})

    if request.method != 'POST':
        return JsonResponse({'error': True, 'msg': 'invalid_request'})
    
    if 'username' not in request.POST or 'password' not in request.POST:
        return JsonResponse({'error': True, 'msg': 'invalid_post'})

    username = request.POST['username']
    password = request.POST['password']

    if len(username) < 3 or len(password) < 3:
        return JsonResponse({'error': True, 'msg': 'invalid_data'})
    
    doesExist = User.objects.filter(username=username).exists()

    if doesExist:
        return JsonResponse({'error': True, 'msg': 'user_already_exist'})

    user = User.objects.create_user(username, password=password)
    # user = authenticate(username=username, password=password)
    auth_login(request, user)
    return JsonResponse({'error': False, 'msg': 'signed'})

Plus

L'assistant précédent de ce cours avait fait un retour il y a 2 ans. Je vous invite à le lire afin de voir se qui pourrait être pertinent pour votre projet. Attention tout de même à ne pas appliquer tout se qui est dit sans réfléchir, certaines remarques ne prennent pas en compte le fait que vous utilisiez peut être un package (comme le Django REST Framework, que certains d'entre vous utilisent). Ayez un regard critique sur tout se que je vous ai dit plus haut et sur tout se qui est dit dans le document suivant. Django 2018 - 2019 | Feedback-Dom-projets-Django

A+
Alex - SpicyPaper