이번 2차 프로젝트에서 가장 많은 시간을 들였고 사실 가장 아쉬운 부분이기도 했던 부분이 바로 리스트 페이지를 불러오는 기능입니다.
원래 하고 싶었던 기능은 스탯 4가지를 교집합으로 필터링하여 체력과 지능을 선택하면 체력과 지능 두 가지 스탯을 모두 가지고 있는 강의만 나오게 하고 싶었는데 교집합이 아닌 합집합만 나와서 결국 교집합 기능구현은 리팩토링 때 꼭 해내고 말겠다고 마음먹게 만든....그런 기능입니다.
제가 작성한 코드는 다음과 같습니다.
class ProductListView(View):
@AuthorizeProduct
def get(self,request):
category = request.GET.get('category', None)
sub_category = request.GET.get('sub_category', None)
stat = request.GET.getlist('stat', None)
q=Q()
if category:
q &=Q(sub_category__category__name=category)
if sub_category:
q &=Q(sub_category__name=sub_category)
if stat:
q &=Q(coursestat__stat__name__in=stat)
products = Course.objects.prefetch_related('like_set').filter(q).distinct()
results=[{ "course_id" : product.id,
"thumbnail" : product.thumbnail_image_url,
"user_name" : product.user.name,
"sub_category" : product.sub_category.name,
"course_name" : product.name,
"price" : product.price,
"payment_period" : product.payment_period,
"discount_rate" : product.discount_rate,
"discount_price" : product.price * product.discount_rate / 100,
"course_like" : product.like_set.count(),
"is_like_True" : product.like_set.filter(user_id=request.user).exists()
} for product in products]
return JsonResponse({"results" : results}, status=200)
Q객체를 활용하면 catgory/sub_category/stat에 맞는 강의를 가져오는 기능입니다. 이 코드는 코드리뷰하면서도 좋지 못한 코드라는 멘토님의 리뷰를 받았습니다.
이유는 if문을 많이 사용하여 코드가 선형적이지 못하다는 이유 때문입니다. 멘토님의 리뷰 후 수정된 코드는 다음과 같습니다.
class ProductListView(View):
FILTERS = {
"category" : Q(sub_category__category__name=category),
"sub_category" : Q(sub_category__name=sub_category)
"stat" : Q(coursestat__stat__name__in=stat)
}
[Q(sub_category__category__name=category), Q(sub_category__name=sub_category), Q(coursestat__stat__name__in=stat)]
Q(Q(sub_category__category__name=category), Q(sub_category__name=sub_category))
@AuthorizeProduct
def get(self,request):
query = functools.reduce(lambda q1, q2: q1.add(q2, Q.AND), [FILTERS.get(request.GET[key], Q()) for key in request.GET.keys()])
products = Course.objects.filter(query).distinct()
아직 해당코드를 완벽하게 이해하지는 못했지만 if문을 하나도 사용하지 않은 선형적인 코드라는 것은 확실합니다.
이번 코드리뷰를 받기 전까지는 그저 기능을 구현하는것에만 신경써서 이 코드가 정말 좋은 코드인지 고민해보는 시간이 부족했던 것 같습니다.
앞으로 개발자로 성장하는 과정 가운데 단순히 기능구현에만 만족하는 것이 아니라 어떻게 선형적인 코드를 잘 작성할 수 있을지 고민해봐야 될 것 같습니다.