Design Pattern and Refactoring

M.Fakhruddin Hafizh
AdHub Team
Published in
6 min readApr 17, 2019

Design Pattern

Design Pattern merupakan solusi secara general untuk mengatasi masalah yang sering tejadi dalam desain perangkat lunak. Dengan menggukan design pattern kita dapat mempercepat proses pengembangan dengan menggunakan paradigma pengembangan yang sudah teruji dan terbukti. Selain itu, dengan menggunakan design patter kita dapat mencegah masalah yang kecil menjadi besar.

Secara garis besar, terdapat tiga tipe design pattern yaitu creational, structural, dan behavioral

Creational

Design pattern tipe ini berhubungan dengan insialisasi sebuah kelas. Design pattern yang merupakan tipe creational antara lain:

  • Abstract Factory

Membuat instance dari beberapa families of class

  • Builder

Memisahkan object construction dengan objeknya

  • Factory Method

Membuat instance dari beberapa child class

  • Prototype

Membuat sebuah instance yang fully initialized untuk dikloning

  • Singleton

Sebuah class hanya boleh memiliki satu instance

Structural

Design pattern tipe structural berhubungan tentang komposisi(struktur) class dan objek. Design pattern yang merupakan tipe structural antara lain:

  • Adapter

Membuat sebuah interface yang dapat menghubungkan class satu dengan class lainnya

  • Bridge

Memisahkan interface objek dari implementasinya

  • Composite

Merupakan sebuah struktur tree dari simple dan composite objek

  • Decorator

Menambahkan responsibility kepada sebuah objek secara dinamis

  • Facade

Sebuah class dapat merepresentasikan seluruh subsistem

  • Flyweight

Membuat instance yang ringan dan digunakan secara efisien secara bersama

Behavioral

Design pattern tipe ini behubungan tentang komunikasi(perilaku/behavior) sebuah class dengan class lainnya. Design pattern yang merupakan tipe behavioral antara lain:

  • Chain of responsibility

Melakukan passing request antara serangkaian object

  • Command

Melakukan enkapsulasi dengan cara menjadikan command request menjadi object

  • Iterator

Mengakses seluruh elemen pada sebuah struktur data secara berurutan

  • Memento

Menyimpan state sebuah objek yang nantinya akan digunakan untuk melakukan proses undo

  • Observer

Sebuah cara untuk memberitahu perubahan yang terjadi kepada sejumlah class

  • Strategy

Melakukan enkapsulasi algoritma menjadi sebuah class

Selain tiga tipe pattern utama yang telah disebutkan diatas, masih ada satu tipe design pattern lainnya yaitu compound pattern. Compound pattern merupakan penggabungan dari beberapa design pattern.

Penerapan Design Pattern Pada Pengembangkan AdHub

Dalam mengembangkan perangkat lunak AdHub kami memanfaat compound design patter yaitu MVC(Model View Controller). MVC merupakan gabungan dari observer, composite, dan strategy pattern. Berikut merupakan implementasi kami

  • Model
class PemasangIklan(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
full_name = models.CharField(max_length=30)
telepon = models.CharField(max_length=12)
customer_id = models.CharField(max_length=12, default='0')


class Iklan(models.Model):
id = models.AutoField(primary_key=True)
judul = models.CharField(max_length=100)
platform = models.IntegerField(choices=PLATFORM_IKLAN)
tanggal_mulai = models.DateTimeField()
tanggal_berakhir = models.DateTimeField()
deskripsi = models.TextField()
image = models.ImageField(upload_to='static/saved_image')
link_iklan = models.URLField()
pemasang_iklan = models.ForeignKey(User, on_delete=models.CASCADE)
nama_usaha = models.CharField(max_length=20)


class Pembayaran(models.Model):
id = models.OneToOneField(Iklan, primary_key=True, on_delete=models.CASCADE)
status = models.CharField(max_length=20)
total = models.IntegerField()
pemasang_iklan = models.ForeignKey(User, on_delete=models.CASCADE)
bank_pengirim = models.CharField(max_length=10, null=True)
no_rekening = models.CharField(max_length=20, null=True)
bukti = models.ImageField(null=True)
  • View
{% extends "base-authenticated.html" %}
{% load staticfiles %}
{% load static %}
{% block content %}
<div class="container">
{% include "container/new_ad/platform.html" %}
</div>
{% endblock %}
  • Controller
def iklan_index(request):
response['title'] = 'Adhub'

return render(request, 'platform.html', response)


@csrf_exempt
def set_cookie(request):
check = dict(request.POST.lists())
platform = check["platform[]"]
response = HttpResponse("cookie set")
response.set_cookie('platform', platform, expires=2 * 60 * 60)
return response

Refactoring

“The process of changing a software system in such a way that it does not alter the external behaviour of the code yet improves the internal structure.”

Refactoring merupakan sebuah proses melakukan perubahan internal perangkat lunak sehingga menjadi lebih baik, mudah untuk dipahami, dan mudah dimodifikasi tanpa mengubahan perilaku kode.

Kanapa kita harus melakukan refactoring?

  • Refactoring meningkatkan desain perangkat lunak
  • Refactoring membuat perangkat lunak lebih mudah dipahami
  • Refactoring membantu kita menemukan bug
  • Refactoring membantu kita memprogram lebih cepat

Kapan kita harus melakukan refactoring?

  • Refactoring saat kita menambahkan fungsi
  • Refactoring saat kita perlu memperbaiki bug
  • Refactoring saat kita melakukan review kode

Extract Method

Apabila kita memiliki bagian kode yang dapat dikelompokkan bersama maka kita ubah bagian kode tersebut menjadi method yang memiliki nama yang menjelaskan tujuan method tersebut. Sebagai contoh

#Sebelum extract method
Class Customer(
public String statement() {
double totalAmount = 0;
int frequentRenterPoints = 0;

Iterator<Rental> iterator = rentals.iterator();
String result = "Rental Record for " + getName() + "\n";

while (iterator.hasNext()) {
Rental each = iterator.next();
double thisAmount = 0;

// Determine amount for each line
switch (each.getMovie().getPriceCode()) {
case Movie.REGULAR:
thisAmount += 2;
if (each.getDaysRented() > 2)
thisAmount += (each.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented() * 3;
break;
case Movie.CHILDREN:
thisAmount += 1.5;
if (each.getDaysRented() > 3)
thisAmount += (each.getDaysRented() - 3) * 1.5;
break;
}

// Add frequent renter points
frequentRenterPoints++;

// Add bonus for a two day new release rental
if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&
each.getDaysRented() > 1)
frequentRenterPoints++;

// Show figures for this rental
result += "\t" + each.getMovie().getTitle() + "\t" +
String.valueOf(thisAmount) + "\n";
}
result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";

return result;
}

Dilakukan extract method pada statment

#Sesudah extract method
class Customer {
public String statement() {
Iterator<Rental> iterator = rentals.iterator();
String result = "Rental Record for " + getName() + "\n";

while (iterator.hasNext()) {
Rental each = iterator.next();

// Show figures for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ String.valueOf(each.getCharge()) + "\n";
}

// Add footer lines
result += "Amount owed is " + String.valueOf(getTotalCharge()) + "\n";
result += "You earned " + String.valueOf(getTotalFrequentRenterPoints())
+ " frequent renter points";

return result;
}
private double getTotalCharge(){
double result = 0;
Iterator<Rental> iterator = rentals.iterator();
while (iterator.hasNext()){
Rental each = iterator.next();
result += each.getCharge();
}
return result;
}

// Add frequent renter points
private int getTotalFrequentRenterPoints(){
int result = 0;
Iterator<Rental> iterator = rentals.iterator();
while (iterator.hasNext()){
Rental each = iterator.next();
result += each.getFrequentRenterPoints();
}
return result;
}

}

Move Method

Apabila sebuah method lebih banyak digunakan oleh class lain maka kita dapat membuat method baru dengan body serupa di class yang paling banyak menggunakannya.

Replace Temp with Query

Apabila kita menggunakan temporary variable(temp) untuk menyimpan sebuah nilai maka kita extract ekpresi temp tersebut menjadi method.

--

--