Design Patterns? Refactor? Apa itu?

Indra Septama
PPL C6 Big Data
Published in
4 min readMay 29, 2019

Menghasilkan code bersifat clean code merupakan salah tujuan dari developer. Sebelumnya saya pernah membahas tentang clean code, silahkan check disini. Untuk menghasilkan code yang bersifat clean code, penting untuk memahami konsep design pattern dan refactor. Dua konsep ini pernah saya pelajari ketika mengambil kuliah Pemrograman Lanjut di Fasilkom UI. Walaupun saat itu nilai saya tidak memuaskan tapi izinkan saya untuk menjelaskan design pattern dan refactor, hehehehe :)

https://memegenerator.net/img/instances/68244482/design-patterns-pfft-i-just-write-code.jpg

Design Pattern

Design pattern adalah solusi (best practice) umum untuk masalah yang sering terjadi dalam pengembangan software. Secara umum, ada tiga klasifikasi design pattern, yaitu

  • Creational pattern, design pattern ini membahas tentang bagaimana sebuah instance/objek dibuat, bagaimana kita membuat objek yang cocok dengan situasi, kondisi, serta kebutuhan yang ada
  • Structural pattern, design pattern ini lebih berfokus pada bagaimana relasi atau hubungan antar objek terjadi, bagaimana caranya agar dua objek yang berbeda bisa saling bekerja sama, bagaimana membuat flow task lebih mudah dan manageable, dan lain-lain.
  • Behavioral pattern, design pattern ini lebih fokus untuk membahas isu terkait flow komunikasi antar objek-objek yang ada. Bagaimana caranya agar task dapat dilakukan oleh sebuah objek dengan lebih terstruktur, bagaimana caranya agar task dapat berjalan secara general, namun hasilnya dapat disusun secara custom.

Refactor

Refactor adalah salah satu komponen dari tiga komponen pada proses TDD yaitu test (red), implement (green), refactor (blue). Menurut buku Martin Fowler, refactor adalah proses mengubah sistem dari suatu perangakat lunak tanpa mengubah perilaku eksternal (fungsionalitas akhir) dari perangkat lunak tersebut. Tujuan utama dari refactor adalah meningkatkan kualitas struktur internal dari perangkat lunak. Refactor merupakan langkah untuk “membersihkan” code sehingga dapat meminimalkan peluang munculnya software defect (bug) pada implementasi yang dibuat. Jadi secara umum, ketika kita melakukan refactor, kita sedang meningkatkan kualitas desain dari perangkat lunak kita.

Implementasi

Kami menerapkan beberapa konsep design pattern, salah satunya adalah decorator pattern. Decorator Pattern adalah pattern yang digunakan untuk menambahkan fungsionalitas baru ke dalam objek tanpa merubah struktur objek tersebut. Decorator Pattern termasuk ke dalam Structural Pattern. Hal ini dikarenakan kami menggunakan ReactJS. Penggunaan decorator pattern ini terlihat pada class MapChoropleth yang dapat diubah dengan fleksibel melalui props yang dikirim oleh parent component.

Parent component mengirim props sesuai kondisi parent.

generateGeoJSON = (id, dataJSON, batas, isCity, zoom, param, category) => {
return (
<MapChoropleth
ID={id}
data={dataJSON}
batas={batas}
isCity={isCity}
zoom={zoom}
param={param}
category={category}
/>
);
};

Sedangkan child component(class MapChoropleth) akan menerima props yang dikirim dari parent component.

componentWillReceiveProps = ({
id,
batas,
data,
isCity,
zoom,
param,
category
}) => {
this.setState({
ID: id,
batas: batas,
data: data,
isCity: isCity,
zoom: zoom,
param: param,
category: category
});
};

Sedangkan refactor, kami juga menerapkan di banyak hal. Salah satunya adalah mengubah class Choropleth yang sebelumnya belum menjadi component React yang terstruktur menjadi class yang terstruktur.

Sebelum direfactor

import React from "react";
import PropTypes from "prop-types";
import Choropleth from "react-leaflet-choropleth";

const onEachFeature = (feature, layer) => {
const namaDaerah = feature.properties.NamaDaerah;

layer.bindPopup(namaDaerah);
};

const getColor = (condition, listBatas) => {
const batas1 = listBatas[0];
const batas2 = listBatas[1];
const batas3 = listBatas[2];
const batas4 = listBatas[3];
const batas5 = listBatas[4];
const batas6 = listBatas[5];

console.log(listBatas);
if (condition < batas1) {
return "#d73027";
}
if (condition >= batas1 && condition < batas2) {
return "#fdae61";
}
if (condition >= batas2 && condition < batas3) {
return "#fee08b";
}
if (condition >= batas3 && condition < batas4) {
return "#d9ef8b";
}
if (condition >= batas4 && condition < batas5) {
return "#a6d96a";
}
if (condition >= batas5 && condition < batas6) {
return "#66bd63";
}
return "#1a9850";
};

let Batas;

const styleGeoJSON = feature => {
return {
fillColor: getColor(feature.properties.ID, Batas),
weight: 2,
opacity: 1,
color: "white",
dashArray: "3",
fillOpacity: 0.7
};
};

const MapChoropleth = ({ ID, batas, dataJSON }) => {
Batas = batas;
return (
<Choropleth
data={dataJSON}
key={ID}
style={styleGeoJSON}
onEachFeature={onEachFeature}
/>
);
};

MapChoropleth.propTypes = {
ID: PropTypes.string.isRequired,
batas: PropTypes.arrayOf(PropTypes.number),
dataJSON: PropTypes.element
};

MapChoropleth.defaultProps = {
batas: [],
dataJSON: {}
};

export default MapChoropleth;

Setelah direfactor

import PropTypes from "prop-types";
import Choropleth from "react-leaflet-choropleth";
import React, { Component } from "react";

class MapChoropleth extends Component {
static propTypes = {
id: PropTypes.number,
data: PropTypes.shape({ root: PropTypes.string.isRequired }),
batas: PropTypes.instanceOf(Array)
};

static defaultProps = {
id: 0,
data: {},
batas: []
};

constructor({ id, batas, data, isCity, zoom, param, category }) {
super();
this.state = {
ID: id,
batas: batas,
data: data,
isCity: isCity,
zoom: zoom,
param: param,
category: category
};
this.onEachFeature = this.onEachFeature.bind(this);
}

componentWillReceiveProps = ({
id,
batas,
data,
isCity,
zoom,
param,
category
}) => {
this.setState({
ID: id,
batas: batas,
data: data,
isCity: isCity,
zoom: zoom,
param: param,
category: category
});
};

styleGeoJSON = feature => {
const { batas } = this.state;
return {
fillColor: this.getColor(
this.state.param[feature.properties.ID][this.state.category],
batas
),
weight: 2,
opacity: 1,
color: "white",
dashArray: "3",
fillOpacity: 0.7
};
};

onEachFeature = (feature, layer) => {
const namaDaerah = feature.properties.NamaDaerah;

layer.bindPopup(namaDaerah);
// console.log(!this.state.isCity || this.state.zoom > 7);
// if (!this.state.isCity || this.state.zoom > 7) {
// layer.bindTooltip(namaDaerah, {
// permanent: true,
// direction: "center",
// className: "my-labels"
// });
// }
};

getColor = (condition, listBatas) => {
const batas1 = listBatas[0];
const batas2 = listBatas[1];
const batas3 = listBatas[2];
const batas4 = listBatas[3];
const batas5 = listBatas[4];
const batas6 = listBatas[5];

if (condition < batas1) {
return "#d73027";
}
if (condition >= batas1 && condition < batas2) {
return "#fdae61";
}
if (condition >= batas2 && condition < batas3) {
return "#fee08b";
}
if (condition >= batas3 && condition < batas4) {
return "#d9ef8b";
}
if (condition >= batas4 && condition < batas5) {
return "#a6d96a";
}
if (condition >= batas5 && condition < batas6) {
return "#66bd63";
}
return "#1a9850";
};

render() {
const { data, ID } = this.state;
return (
<Choropleth
data={data}
key={ID}
style={this.styleGeoJSON}
onEachFeature={this.onEachFeature}
/>
);
}
}

export default MapChoropleth;

Demikian pejelasan mengenai design pattern dan refactor dari saya. Semoga hari kalian menyenangkan!

--

--