Request Response & Task Pattern

Untuk kerja as a team diperlukan pattern yang bagus, agar hasil yang dicapai berjalan dengan sempurna. Namun kerja dengan framework tidaklah cukup. Kita juga harus memahami kemampuan masing-masing tim dalam project. case study :

Untuk membuat aplikasi android yang kompleks dibutuhkan 2 orang developer. Dengan harapan target tercapai tepat waktu. Namun perlu diketahui kemampuan dari masing-masing developer berbeda ada yang 70% skil di UI dan ada yang 70% skill di logic. Belum lagi satu dari dua developer tersebut adalah junior yang hanya menguasai dasar-dasar java/hanya mengenal UI. Untuk itu terjadi ketimpangan beban project.

Oleh karena itu, jika kita membagi pengerjaan Apps adalah base on screen contoh :

  1. Screen Login : developer A
  2. Screen Register : developer A
  3. Screen Dashboard : developer B
  4. Screen Detail : developer B
  5. dst…

yang terjadi adalah pengerjaan apps akan terjadi

  1. Akan ada saling tunggu
  2. Merge berantakan
  3. Task jadi pilah pilih
  4. UI dan Logic jadi berbeda hasil, jika developer A mengerjakan UI dan developer B mengerjakan UI asal selesai. yang terjadi berikutnnya adalah developer A wajib membenahi UI developer B begitu juga dengan Logic

Berkaca dari itu GITS membagi team menjadi dua yaitu Android UI dan Android Logic. So, apa yang terjadi selanjutnnya? hasil UI jadi seragam sama rapi dan logic jadi seragam sama rapi. Namun masih terjadi kendala karena kita masih ada waktu tunggu. Ya waktu tunggu untuk UI selesai dengan baik maka Logic pun dikerjakan.

So, apa yang terjadi selanjutnnya? Membuat pattern yang mendukung kasus tersebut.

Hipotesis dengan konsep Request dan Response.

Apa itu Request dan Response? berkaca dari clean-swift.org yang menerapkan VIP cycle, penggunaan yang dirasa cukup clean untuk bekerja as a team. Maka munculah ide untuk bagai mana jika kita menyerdehanakan lagi dari clean-swift how?

Clean Swift terdiri dari beberapa file :
  1. View + interface : untuk view
  2. Present + interface: data yang akan ditampilkan ke view
  3. Interactor + interface : semua logic api dan lain sebagainnya di taroh disini
  4. Route : routing antar view
  5. Configurator : config dari semua class
  6. Worker : digunakan untuk task yang bersifat storage atau baground processing (jarang dipake)
  7. Model : model yang akan dipakai untuk request dan response
So, inisiatif pemangkasan pun terjadi. Sehingga menjadi berikut
  1. View : segala macam view terjadi disini
  2. Present : segala macam logic terjadi disini
  3. RequestInterface : request method
  4. ResponseInterface : response method
  5. Configurator : config semua file dan hanya di inisiasi satu kali
  6. Model : model yang digunakan untuk request dan response

So, codennya gimana? Berikut contoh dari base Apps

Base Activity

public abstract class BaseActivity extends AppCompatActivity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayout());
init();
}

protected abstract @LayoutRes int getLayout();
protected abstract void init();
}

Sebelum ke tahapan selanjutnnya disini saya membagai menjadi dua Task :

UI, scope pengerjaan meliputi :
  1. XML
  2. Activity
  3. Definisi Request
  4. Definisi Response
  5. Buat Present
  6. Buat Todo
Logic, scope pengerjaan meliputi :
  1. Baca parameter dari Request
  2. Buat logic di Present
  3. Lempar data ke Response untuk ditampilkan di Activity
  4. Finish Todo

Jika digambarkan dengan diagram maka akan seperti berikut :

request response

Konsepnnya sederhana, Jika kalian pernah menggunakan HTTP request maka sama halnnya dengan konsep tersebut. Kita request dengan parameter dan kita dapat response dan kita tidak tau betapa rumitnya Logic yang digunakan di backend.

Yang menjadi perhatian adalah :

UI hanya merequest dan menerima hasil akhir. Bukan untuk memproses request dan memproses kembali data yang sudah di proses oleh Logic

Artinnya segala macam bentuk :

  1. Validasi
  2. HTTP Request
  3. Session
  4. Storage
  5. Logic
  6. Sync Data
  7. dst…

Semua berada di Logic… Jangan sampai salah ya guys….

Request dan Response

interface MainRequest extends BaseRequest{
void doPrintNameApps(boolean isMVP);
}
interface MainResponse extends BaseResponse{
void displayNameApps(String nameApps);
}

Request dan Response digunakan sebagai perantara antara UI dan Logic. Untuk pemberian nama method gunakan kata do sebagai request dan display untuk melakukan response. Tujuannnya agar mudah dibaca dan mudah dimengerti oleh developer. Sangat berguna juga buat TDD.

Ingat Do dan Display

Activity sebagai View

public class MainActivity extends BaseActivity implements MainResponse {
public MainRequest input;

@Override
protected int getLayout() {
return R.layout.activity_main;
}

@Override
protected void init() {
ConfiguratorActivity.newInstance().configMain(this);
input.doPrintNameApps(!false);
}

@Override
public void onError(String error, Object object) {
Log.e("this error",error);
}

@Override
public void displayNameApps(String nameApps) {
Log.d("this apps",nameApps);
}
}

Activity implement dari interface Response. Tujuannnya agar dapat menampilkan hasil yang sudah diproses oleh Logic. Dan juga deklarasi variable input dari interface Request. Tujuannnya agar UI dapat merequest logic.

Present as Logic

public class MainPresent implements MainRequest{
public MainResponse output;
private MainPresentExtension controller;

public MainPresent() {
controller = new MainPresentExtension();
}

/**
*
TODO As a <type of process>, I want <some process> so that <some return process>.
*/
@Override
public void doSomething(Object object) {

}

/**
*
TODO As a <type of process>, I want <some process> so that <some return process>.
* @param isMVP
*/
@Override
public void doPrintNameApps(boolean isMVP) {
if (isMVP) {
output.displayNameApps("IS SUCCESS");
}else{
output.onError("IS ERROR",null);
}
}
}

Present digunakan untuk menampikan request dari UI dan memprosesnnya. Pesent implement dari interface Request dan mendeklarasikan class Response. Dan perlu diketahui UI juga diwajibkan menggunakan TODO.

TODO Genks… Iya TODO…

Jarang sekali kita menggunakan TODO. TODO fitur digunakan agar antar developer bisa saling berkomunikasi. Tutorial penggunaan TODO dapat dilihat disini https://www.jetbrains.com/help/idea/2016.2/using-todo.html. Yang menarik adalah penulisan TODO tidak boleh sembarangan, tapi menggukan metode User Story di Scrum management.

TODO As a <type of process>, I want <some process> so that <some return process>.

Contoh :

TODO As a Login Process, I want Request With username & password so that result with UserLoginModel.

Contoh lagi :

TODO As a Profile User Process, I want display profile user from share preference so that result with UserDao if success & go To Login if fail.

Diharapkan dengan penulisan tersebut dapat memudahkan developer saling berkomunisaksi antara UI dan Logic. Gampang Bukan?

Configurator Sebagai Jembatan

public class ConfiguratorActivity{

public static ConfiguratorActivity newInstance;

public static ConfiguratorActivity newInstance() {
if (newInstance == null){
newInstance = new ConfiguratorActivity();
}
return newInstance;
}

public void configMain(MainActivity activity){
MainPresent present = new MainPresent();
activity.input = present;
present.output = activity;
}
}

Configurator digunakan sebagai jembatan atau penghubung antara View,Present,Response dan Request. Class ini dapat dipergunakan untuk banyak screen / banyak kasus. Dan bisa juga di Joinkan menggunakan Dagger.

Gampang Bukan?

Penamaan package

Penamaan package, selama bekerja sebagai developer GITS saya menyimpulkan penamaan package disesuaikan dengan screen. Contoh untuk halaman Login, penamaan package adalah id.gits.nameapps.login baru didalam package login nantinnya terdiri dari beberapa file, seperti activity, fragment, present, request, response dan sebagainya yang berhubungan dengan login. Namun untuk API kami menggunakan module. Dengan penamaan package tersebut kami dapat dengan mudah menemukan dan mengelompokan file yang dibutuhkan oleh screen. Kembali lagi ini masalah selera.

GIT REPO with GIT FLOW

Git flow adalah mekanisme branch yang memudahkan developer untuk saling berkolaborasi. Bisa di baca di sini guys http://danielkummer.github.io/git-flow-cheatsheet/. Sedangkan untuk tools saya mengunakan Source Tree dan untuk linux bisa menggunakan Git Kraken.

GIT Flow Genks…

Kembali ke topik, di GIT flow ada branch feature. Untuk konsep ini penamaan feature harus diatur agar memudahkan developer mengetahui apa saja yang sudah dikerjakan berdasarkan jobdesknnya. Untuk UI penamaan featur <namafeature>_view dan untuk logic <namafeature>_logic.

Mudah bukan, penggunaan pattern Request dan Response? Tapi wait… ada yang kurang. Apa itu?

  1. Logic menunggu kerjaan UI kelar sehingga Logic ada waktu tunggu
  2. Sering terjadi bentrok ketika memberikan Dummy Data oleh UI. Biasannya kerubah sama Logic.
Solusinnya adalah EXTENSION

Whaattt… Extension? Yups, extension adalah class yang digunakan sebagai perpanjangan tangan dari Present. Tujuannya adalah menghindari waktu tunggu Logic mengerjakan jobdesknnya dan UI dapat menampilkan data Dummy dan meminimalisir bentrok.

Extension sebenernnya hanya ada di Swift. Tapi kita bisa menggunakan Class sebagai penggantinnya.

public class MainPresentExtension {
public void getNameApps(boolean isResult,MainResponse output){
if (isResult) {
output.displayNameApps("MVP");
}else {
output.onError("NOT MVP",null);
}
}
}

Dan jika Logic sudah selesai mengerjakan tasknnya maka di Present dia wajib mengganti proses yang ada di method do dengan method yang ada di class extension, dan TODO diganti jadi DONE.

/**
* DONE As a <type of process>, I want <some process> so that <some return process>.
*
@param isMVP
*/
@Override
public void doPrintNameApps(boolean isMVP) {
controller.getNameApps(isMVP,output);
}

Dengan demikian Developer Logic dapat mengerjakan logic yang lain sembari UI menyelesaikan pekerjaannnya. Begitu juga UI dapat memberikan data Dummy sembari menunggu pengerjaan logic selesai.

Mudah Bukan?

Pattern ini bisa digabungkan dengan Data Binding, Rx, Dagger, dan lain-lain. Anda bisa explore lebih jauh tentang hipotesa saya ini.

Semoga tulisan, ini dapat bermanfaat bagi Developer Indonesia. Dan perlu di ingat tulisan ini masih hipotesa dan masih dalam kajian. dan GITS sedang mengkaji itu.