[Objective] vues.py - Refactoring de la fonction routine_detail #41

Open
opened 2020-10-28 21:35:32 +01:00 by Fred · 1 comment
Owner

Oyo,

Ta fonction routine_detail (au pluriel, cf #...) ressemble à ceci:

routine = get_object_or_404(Routine, pk=routineid)

    rank = 0
    level = 0
    difficulty = 0
    age_boy = 0
    age_girl = 0
    is_competitive = True

    for skill_link in routine.skill_links.all():

        difficulty += skill_link.skill.difficulty

        if skill_link.skill.level > level:
            level = skill_link.skill.level

        if skill_link.skill.rank > rank:
            rank = skill_link.skill.rank + 1

        if not skill_link.skill.is_competitive:
            is_competitive = False

        if skill_link.skill.ageBoy is not None and skill_link.skill.ageBoy > age_boy:
            age_boy = skill_link.skill.ageBoy

        if skill_link.skill.ageGirl is not None and skill_link.skill.ageGirl > age_girl:
            age_girl = skill_link.skill.ageGirl

    if routine.skill_links.all().count() != 10:
        is_competitive = False

    routine.difficulty = difficulty

    if routine.level < level:
        routine.level = level

    if routine.rank is None or routine.rank < rank:
        routine.rank = rank

    if routine.ageBoy is None or routine.ageBoy < age_boy:
        routine.ageBoy = age_boy

    if routine.ageGirl is None or routine.ageGirl < age_girl:
        routine.ageGirl = age_girl

    routine.is_competitive = is_competitive

    routine.save()

Donc, si je comprends bien, tu prends ta série, et tu essaies de récupérer les valeurs maximales pour les propriétés rank, level, age_boy, age_girl et la somme des difficultés connues.

Mais cela signifie que ta base de données est dénormalisée, et potentiellement pas à jour: si aucun utilisateur ne se rend sur cette fonction routine_details, la série ne sera jamais mise à jour.

Une idée serait de passer par des agrégations (cf. https://docs.djangoproject.com/en/3.1/topics/db/aggregation/#cheat-sheet), avec les fonctions Sum et Max:

from django.db.models import Max, Sum

routine.skill_links.aggregate(Max("level"))
routine.skill_links.aggregate(Sum("difficulty"))
...

Ce ne serait pas obligatoirement plus performant (quoique, si skill_links est mis en cache via un prefect_related), mais cela simplifiera beaucoup la lecture du code.

Oyo, Ta fonction `routine_detail` (au pluriel, cf #...) ressemble à ceci: ```python routine = get_object_or_404(Routine, pk=routineid) rank = 0 level = 0 difficulty = 0 age_boy = 0 age_girl = 0 is_competitive = True for skill_link in routine.skill_links.all(): difficulty += skill_link.skill.difficulty if skill_link.skill.level > level: level = skill_link.skill.level if skill_link.skill.rank > rank: rank = skill_link.skill.rank + 1 if not skill_link.skill.is_competitive: is_competitive = False if skill_link.skill.ageBoy is not None and skill_link.skill.ageBoy > age_boy: age_boy = skill_link.skill.ageBoy if skill_link.skill.ageGirl is not None and skill_link.skill.ageGirl > age_girl: age_girl = skill_link.skill.ageGirl if routine.skill_links.all().count() != 10: is_competitive = False routine.difficulty = difficulty if routine.level < level: routine.level = level if routine.rank is None or routine.rank < rank: routine.rank = rank if routine.ageBoy is None or routine.ageBoy < age_boy: routine.ageBoy = age_boy if routine.ageGirl is None or routine.ageGirl < age_girl: routine.ageGirl = age_girl routine.is_competitive = is_competitive routine.save() ``` Donc, si je comprends bien, tu prends ta série, et tu essaies de récupérer les valeurs maximales pour les propriétés `rank`, `level`, `age_boy`, `age_girl` et la somme des difficultés connues. Mais cela signifie que ta base de données est dénormalisée, et potentiellement pas à jour: si aucun utilisateur ne se rend sur cette fonction `routine_details`, la série ne sera jamais mise à jour. Une idée serait de passer par des agrégations (cf. https://docs.djangoproject.com/en/3.1/topics/db/aggregation/#cheat-sheet), avec les fonctions `Sum` et `Max`: ```python from django.db.models import Max, Sum routine.skill_links.aggregate(Max("level")) routine.skill_links.aggregate(Sum("difficulty")) ... ``` Ce ne serait pas obligatoirement plus performant (quoique, si `skill_links` est mis en cache via un `prefect_related`), mais cela simplifiera beaucoup la lecture du code.
Fred added this to the Revue de l'application `objective` milestone 2020-10-28 21:35:32 +01:00
Fred added the
enhancement
label 2020-10-28 21:35:32 +01:00
Sulley was assigned by Fred 2020-10-28 21:35:32 +01:00
Author
Owner

Du coup, on peut garder la dénormalisation, à une condition: il faut que l'ajout d'un nouveau skill exige le recalcul des informations de la routine.

Du coup, on peut garder la dénormalisation, à une condition: il faut que l'ajout d'un nouveau skill exige le recalcul des informations de la routine.
Sign in to join this conversation.
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Sulley/khana#41
No description provided.