Faites-le en deux boucles
Venant d'une formation en informatique, je soupçonne que le mot « efficacité » doit déjà faire partie de mon cerveau quelque part. Tous ces arbres que j'ai traversés, les grands Os et les omégas étaient là pour m'aider à adopter l'approche la plus efficace. Et oui - ils sont parfois utiles, et je suis fier des questions de CP que je peux résoudre avec eux. Si vous vous trouvez dans le domaine de l'ingénierie produit comme moi, vous partagerez peut-être mon point de vue selon lequel la notion d'efficacité dans l'ingénierie produit n'est pas celle que nous avons apprise à l'université. J'ai accepté cette divergence. Après tout, mon directeur d'école primaire a obtenu un diplôme d'ingénieur en aérospatiale et en a fait le meilleur usage.
L'un des modèles notables que j'avais l'habitude d'écrire dans le code de logique métier qui aspire à l'efficacité est le modèle consistant à tout faire en une seule boucle. Je tombe parfois dessus par d'autres ingénieurs également, généralement à partir de contributions au début de leur carrière.
Voici un morceau de code qui calcule les notes moyennes d'un groupe d'étudiants sur plusieurs semestres, puis renvoie une carte de hachage avec les identifiants des étudiants comme clés :
avgFinalGradesByStudent := make(map[studentID]float)
for _, student := range students {
totalFinalGrades := 0.0
for _, semester := range semesters {
studentGrade := gradesRepository.getByStudentID(student.ID, semester) // fetch from db
totalFinalGrades = totalFinalGrades + studentGrade.FinalGrade
}
avgFinalGradesByStudent[student.ID] := totalFinalGrades / len(semesters)
}
return avgFinalGradesByStudent
studentGrades := make(map[studentID][]float)
for _, student := range students {
for _, semester := range semesters {
semesterGrade := gradesRepository.getByStudentID(student.ID, semester) // fetch from db
studentGrades[student.ID] = append(studentGrades[student.ID], semesterGrade)
}
}
avgFinalGradesByStudent := make(map[studentID]int)
for _, student := range students {
totalFinalGrades := 0
for _, grade := range studentGrades[studentID] {
totalFinalGrades += grade
}
avgFinalGradesByStudent[student.ID] := totalFinalGrades / len(semesters)
}
return avgFinalGradesByStudent
Premièrement, nous avons une séparation claire entre la partie du code qui récupère les données et la partie du code qui effectue le calcul. Avec une simple refactorisation de la méthode d'extraction, notre fonction principale pourrait maintenant ressembler à ceci :
studentGrades := getStudentGradesForAllSemesters(students, semesters)
avgFinalGradesByStudent := calculateAverageFinalGrades(studentGrades)
return avgFinalGradesByStudent
// arrange
studentGrades := map[studentID][]int { 1: []int {97, 86, 51}, 2: []int {60, 85, 95} }
// act
result := calculateAverageFinalGrades(studentGrades)
// assert
assert.Equal(78,result[1])
assert.Equal(80, result[2])
avgFinalGradesByStudent := make(map[studentID]float)
// container for the final results
topThreeGradesByStudent := make(map[studentID][]int)
for _, student := range students {
totalFinalGrades := 0.0
var topThreeGrades []int
for _, semester := range semesters {
studentGrade := gradesRepository.getByStudentID(student.ID, semester) // fetch from db
totalFinalGrades = totalFinalGrades + studentGrade.FinalGrade
// some code to figure out if this grade is the top three grades or not
// and add/remove from topThreeGrades
// ...
}
avgFinalGradesByStudent[student.ID] := totalFinalGrades / len(semesters)
topThreeGradesByStudent[student.ID] := topThreeGrades
}
return avgFinalGradesByStudent, topThreeGradesByStudent
studentGrades := getStudentGradesForAllSemesters(students, semesters)
avgFinalGradesByStudent := calculateAverageFinalGrades(studentGrades)
topThreeGradesByStudent := getTopThreeGradesByStudent(studentGrades)
return avgFinalGradesByStudent, topThreeGradesByStudent
Un autre avantage est que je trouve que je suis plus susceptible de repérer des optimisations beaucoup plus importantes lorsque mon code est facile à lire. Dans l'exemple ci-dessus, par exemple, il devient plus facile de refactoriser la partie qui demande les notes des étudiants en regroupant la demande. Nous devons simplement refactoriser getStudentGradesForAllSemesterssans craindre que d'autres parties de la logique métier soient affectées !
Pour les raisons ci-dessus, je voudrais recommander de faire deux boucles même si vous pouvez faire les deux en une. C'est-à-dire privilégier la séparation logique aux efficacités triviales. Si vous êtes dans un espace d'ingénierie produit similaire à moi, cela facilitera votre travail lorsque vous aurez un code facile à étendre logiquement !
À vous de jouer - avez-vous déjà rencontré ce type de boucles for-it-all-in-one-go? Peut-être que vous le trouviez vraiment bien ? Discutons :)
![Qu'est-ce qu'une liste liée, de toute façon? [Partie 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































