Software Quality Assurance — Class Project Report Episode II

Ibnu Firdaus
4 min readNov 15, 2019

--

Here’s the lesson learned so far…

Source: https://codeintelx.com/wp-content/uploads/2019/01/quality-control-vs-quality-assurance.jpeg

Introduction

Hi component of society, I’m Ibnu Sofian Firdaus, Student in Universitas Indonesia, majoring in Computer Science. This is the second blog post I made as part of my learning in Software Assurance Class while building the class project, which is KAPE (Kanal Akses Pendaftaran KP Elektronik — Electronic Access Channel for Internship Registration). If you’re new, you can read the first part here. So anyway, Let’s see what’s on the menu.

Modularization

In the first sprint, I’ve developed a new feature that could filter vacancies that still opens from those which already closed. To put it simply, I focused on creating feature in the first sprint. In this sprint, I would like to set back my chair and r̶e̶t̶h̶i̶n̶k̶i̶n̶g̶ ̶m̶y̶ ̶l̶i̶f̶e̶ ̶c̶h̶o̶i̶c̶e̶s̶ ̶I̶’̶v̶e̶ ̶m̶a̶d̶e̶ ̶s̶o̶ ̶f̶a̶r̶ focusing more on improving quaility of the code within. But first, why is it important? If it works then it works right? right??

The Importance of Modularization

This section will be filled with content stolen from another website (especially from here) and based on my experiences, so take it with a grain salt. Here goes.

The first benefit of modularization is in the name itself, modular. So what’s the matter then? Well, just imagine there’s a very huge rock boulder and a huge pile in front small rock with same size in front of you. If you’re asked to choose one and carry it, which would it be? Unless you have other motivational reason, or weird thing snapped out of context, or you’re simply just love to suffer, you will pick the pile of small rock, because it is easier to handle and manage, even though it is the same size and weight after all. Just same as programming, modular thing make it easier to handle manage. You need to change behaviour X? well search the function and edit it and just it right away, just make sure it return what it should. Modular code allows us to manage each block independently, thus giving us less constraint and more freedom to what could be done, such as optimization. This aspect alone should make you realize other benefits you could get, but let’s explain it anyway.

As we already know, modularity brings maintainability and convenience in debugging, thanks to independently code we made. This will lead us to better quality of code. Because each parts lives in their own block, it will make it easier for us to improve and fix that block, thus leading us to a much lesser error. Modularity also give us ability to have reusability factor in the code. As we divide the whole code into smaller blocks, which usually takes form as a function, it allows us to use that block in same situation for other places, while giving us assurances of the code being reused. There is also another benefits such as readability, reliability, and many other things. You could research more about it later. For the next part, I’m going to report the work I’ve done as part of exercising this principle.

The Application

So here’s the before code:

def list(self, request, *args, **kwargs):
verified = request.query_params['verified'] if 'verified' in request.query_params else "True"
search = request.query_params['search'] if 'search' in request.query_params else None
if search is not None:
vacancies = Vacancy.objects.filter(Q(name__icontains=search) | Q(company__user__username__icontains=search))
else:
vacancies = Vacancy.objects.all()
companies = [int(x) for x in request.query_params.getlist('company', [])]
if verified.lower() in ("yes", "true", "t", "1"):
vacancies = vacancies.filter(verified=True)
if verified.lower() in {"no", "false", "f", "0"}:
vacancies = vacancies.filter(verified=False)

opened_only = str(request.query_params['opened_only']) \
if 'opened_only' in request.query_params else "False"
if opened_only.lower() in ("yes", "true", "t", "1"):
today = datetime.combine(datetime.now().date(), time())
vacancies = vacancies.filter(close_time__gte=today)

if len(companies) > 0:
. . .

Just look at it, while it is doing just ok, it’s simply not neat and as straightful as it should have been, hey i thought this function would simply get me the list, why the opened_only doing here ? It, for example, reduces readability because we force to fit in as much as we can to one place.

And here’s the after code:

def list(self, request, *args, **kwargs):
search = request.query_params['search'] if 'search' in request.query_params else None
verified = request.query_params['verified'] if 'verified' in request.query_params else "True"
opened_only = str(request.query_params['opened_only']) \
if 'opened_only' in request.query_params else "False"
companies = [int(x) for x in request.query_params.getlist('company', [])]

if search is not None:
vacancies = Vacancy.objects.filter(Q(name__icontains=search) | Q(company__user__username__icontains=search))
else:
vacancies = Vacancy.objects.all()

# Filter vacancies here
vacancies = self.verifiedFilter(vacancies, verified)
vacancies = self.openedJobFilter(vacancies, opened_only)
vacancies = self.companyFilter(vacancies, companies)

page = self.paginate_queryset(vacancies)
. . .

While it is only just slightly better looking (because there is another code from others, along with test-related concern) it, contrary to the one before, improves readability. Hey, what’s this filter about? hmmm… verifiedFilter, guess it filter unverified vacancies out of the list, idk tho… As you can see, it’s hiding the implementation from the this block of code, and this improve the overall quality of the code. In the end, we don’t have to think too much what this variable at line 58 is doing for the function that only does addition, for example.

Just as an addition, here’s the extracted code:

def verifiedFilter(self, vacancies, flag):
if flag.lower() in ("yes", "true", "t", "1"):
vacancies = vacancies.filter(verified=True)
if flag.lower() in {"no", "false", "f", "0"}:
vacancies = vacancies.filter(verified=False)
return vacancies

def openedJobFilter(self, vacancies, flag):
if flag.lower() in ("yes", "true", "t", "1"):
today = datetime.combine(datetime.now().date(), time())
vacancies = vacancies.filter(close_time__gte=today)
return vacancies

def companyFilter(self, vacancies, companies):
if len(companies) > 0:
vacancies = vacancies.filter(company__id__in=companies)
return vacancies

This post discussed about modularization, something we often just ignore away because our code just work as fine as we wanted to. This post also demonstrates a rather simplistic way in doing modularization. These line before closes this blog post.

See you later !

--

--