How to refactor similar looking functions across 2 different class based views in Django 1.10?

238 views Asked by At

Am using codecoverage and it complains that I have 2 functions in 2 different class based views that are too similar.

Attached is the codecoverage error enter image description here

Below are the code that were highlighted:

class PalletContentPickup(APIView):
    """
    Picking up a pallet content to transfer to exiting pallet content
    """
    def put(self, request, pk):
        count = request.data['count']
        pallet_id = request.data['pallet_id']
        from_pallet_content = QuickFind.get_pallet_content_or_404(pallet_content_id=pk)
        to_pallet = QuickFind.get_pallet_or_404(pallet_id=pallet_id)

        Transfer.validate_if_can_pickup_pallet_content(from_pallet_content, to_pallet, request.user)

        to_pallet_content = QuickFind.get_or_create_pallet_content(pallet=to_pallet, product=from_pallet_content.product)
        ExitFormHelper.create_exit_form_line_item_on_pallet_content_if_no_exit_form_line(to_pallet_content, request.user)
        Transfer.previous_pallet_content_to_new_pallet_content(from_pallet_content, to_pallet_content, count)

        serializer = PalletSerializer(from_pallet_content.pallet)
        return Response({"data": serializer.data}, status=status.HTTP_202_ACCEPTED)


class PalletContentPutback(APIView):
    """
    Put back pallet content to an approved pallet
    """
    def put(self, request, pk):
        count = request.data['count']
        pallet_id = request.data['pallet_id']
        from_pallet_content = QuickFind.get_pallet_content_or_404(pallet_content_id=pk)
        to_pallet = QuickFind.get_pallet_or_404(pallet_id=pallet_id)

        Transfer.validate_if_can_putback_pallet_content(from_pallet_content, to_pallet, request.user)

        to_pallet_content = QuickFind.get_or_create_pallet_content(pallet=to_pallet, product=from_pallet_content.product)
        ExitFormHelper.create_exit_form_line_item_on_pallet_content_if_no_exit_form_line(to_pallet_content, request.user)
        Transfer.previous_pallet_content_to_new_pallet_content(from_pallet_content, to_pallet_content, count)

        serializer = PalletSerializer(from_pallet_content.pallet)
        return Response({"data": serializer.data}, status=status.HTTP_202_ACCEPTED)

I read about strategy pattern in Python

Not sure if I should apply strategy pattern here and if so, how? Because the example in the url still does not help me realise exactly how to perform strategy pattern here.

1

There are 1 answers

6
e4c5 On BEST ANSWER

As i see it there is only one line of difference between the two classes. so you can keep it really simple by

class PalletContent(object):
    """
    Put back pallet content to an approved pallet
    """
    def do_action(self, request, pk, action):
        count = request.data['count']
        pallet_id = request.data['pallet_id']
        from_pallet_content = QuickFind.get_pallet_content_or_404(pallet_content_id=pk)
        to_pallet = QuickFind.get_pallet_or_404(pallet_id=pallet_id)

        if action == 'putback':
            Transfer.validate_if_can_putback_pallet_content(from_pallet_content, to_pallet, request.user)
        else:
            Transfer.validate_if_can_pickup_pallet_content(from_pallet_content, to_pallet, request.user)

        to_pallet_content = QuickFind.get_or_create_pallet_content(pallet=to_pallet, product=from_pallet_content.product)
        ExitFormHelper.create_exit_form_line_item_on_pallet_content_if_no_exit_form_line(to_pallet_content, request.user)
        Transfer.previous_pallet_content_to_new_pallet_content(from_pallet_content, to_pallet_content, count)

        serializer = PalletSerializer(from_pallet_content.pallet)
        return Response({"data": serializer.data}, status=status.HTTP_202_ACCEPTED)

class PalletContentPickup(APIView, PalletContent):
     def put(self,request,pk):
         self.do_action(request,pk,'pickup')

class PalletContentPutback(APIView, PalletContent):
     def put(self,request,pk):
         self.do_action(request,pk,'putback')

You are saving only a few lines of code but it may be worth it when it comes to maintenance. At the same time your validate methods do not seem to return anything. Are they raising exceptions?