Living life and Make it Better

life, learn, contribute

Endy Muhardin

Software Developer berdomisili di Jabodetabek, berkutat di lingkungan open source, terutama Java dan Linux.

Intro Framework

Hari ini di milis jug ada yang bertanya tentang framework. Si penanya sendiri kelihatannya mengerti tentang framework, tapi kesulitan menjelaskan kepada orang lain.

Ini umum terjadi, apalagi kalau programmer Java berbicara dengan programmer dari dunia lain, seperti PHP, C, C++, dsb. Ini bisa disebabkan karena penggunaan framework tidak umum di dunia lain tersebut, atau simply karena programmer lain tersebut fakir bandwidth, sehingga gak aware terhadap tren terbaru.

Baiklah, mari kita bahas framework. Framework, sesuai dengan terjemahannya, adalah kerangka kerja. Jadi, di dalam framework ada beberapa kode program yang kalau kita gunakan, akan memberikan kerangka atau struktur ke aplikasi yang dihasilkan. Singkatnya seperti itu. Nanti akan lebih jelas setelah kita lihat contoh kasus dan contoh kode.

Untuk memahami framework, mari kita lihat ke dunia yang minim framework, yaitu PHP. Sebelum tahun 2005-2006 ini, (setau saya) programmer PHP di Indonesia masih asing dengan framework.

Misalnya saya buat aplikasi shopping cart. Aplikasi yang sangat umum dalam PHP. Setidaknya saya pernah mencoding ulang shopping cart minimal tiga kali. Dan semuanya arsitekturnya beda.

Pertama, waktu masih belajar. Semua kode campur aduk jadi satu. Kalau ada perubahan warna font, beberapa kode SQL harus ikut diupdate. Ubah nama tabel, 7 file kode harus diedit. Singkatnya, perubahan sedikit saja memaksa saya mengubah di banyak tempat di kode program.

Kemudian, setelah semakin banyak pengalaman, saya mulai memisahkan kode HTML dengan kode SQL. Dengan ini, aplikasi bisa berganti wajah dengan mudah. Cukup edit satu file konfigurasi, tampilan berubah seketika.

Terakhir, saya mulai mempertimbangkan multi bahasa. Semua string yang berkaitan dengan label, dikeluarkan dalam satu file sendiri. Jadi kalau kita mau ganti bahasa, cukup bikin replika file tersebut, dan terjemahkan. Kemudian edit file konfigurasi, dan bahasa berubah seketika.

Rapi dan bersih ..

Setelah mendapatkan struktur yang optimal, saya mulai me-reuse struktur tersebut. Kapan-kapan membuat aplikasi baru, saya akan langsung memisahkan kode HTML, SQL, dan bahasa.

Skenario di atas terjadi karena saya tidak menggunakan framework. Butuh banyak sekali trial and error buat saya sampai menemukan struktur yang rapi dan bersih. Setelah ditemukan, struktur tersebut saya jadikan framework. Kerangka untuk membuat aplikasi selanjutnya.

Sekarang kita pindah dari dunia yang minim framework, ke dunia yang kebanjiran framework, Java.

Di dunia Java, kelihatannya orang sangat suka coding framework, sehingga kalau kita search di sourceforge, mungkin lebih banyak framework daripada aplikasi siap pakai. Mengapa ini terjadi, saya tidak tahu. Yang jelas, kalau kita akrab dengan Java, pasti akan pakai framework.

Framework yang ideal harusnya merupakan intisari dari best practices. Pengalaman bertahun-tahun membuat aplikasi yang mirip, disimpulkan dan dibakukan menjadi framework siap pakai. Tapi saking banyaknya framework di Java, akhirnya banyak juga framework sampah. Artinya, dibuat bukan dari best practices dan experiences, tapi lebih menjadi ajang belajar membuat framework.

Penggunaan framework hasil belajar seperti ini sangat buruk dampaknya. APInya tidak stabil, sehingga kalau framework tersebut menerbitkan edisi baru, kode program kita harus diubah semua. Tentu saja, karena framework merupakan kerangka utama. Jadi kalau kerangkanya berubah, maka seluruh aplikasi akan terpengaruh. Selain itu, strukturnya juga belum terbukti keandalannya. Masalah sederhana menjadi kompleks, waktu banyak terbuang untuk ‘mengurusi’ framework. Menggunakan framework jelek lebih fatal akibatnya daripada tanpa framework.

Sampai sejauh ini, harusnya sudah ada gambaran tentang framework.

Framework vs Library

Jangan keliru membedakan framework dengan library. Framework, by definition, sangat invasif. Dia memaksakan bagaimana kita harus coding, bagaimana memberi nama class, di mana harus meletakkan file, dan banyak aturan-aturan lain. Sedangkan library, tinggal baca dokumentasi, daftar function, input dan output masing-masing function, selesai.

Dengan demikian, menggunakan framework lebih sulit daripada library. Coba kita bedakan framework dengan library Framework Java:

Library Java:

Framework PHP:

Library PHP:

Ada lagi satu kategori, yaitu toolkit. Toolkit adalah kode yang kita gunakan dalam development, tapi tidak disertakan dalam produk akhir. Contohnya di Java antara lain: Ant dan CruiseControl.

Tapi ada juga beberapa yang tidak jelas pengelompokannya. JUnit misalnya, di satu sisi, dia menyediakan perlengkapan untuk testing sehingga bisa dikategorikan sebagai library. Di sisi lain, dia mengharuskan ada prefix test di setiap nama method, sehingga layak disebut framework.

Plus Minus

Sekarang pertanyaan yang penting. Apa keuntungan dan kerugian menggunakan framework? Asumsikan framework yang ingin digunakan bagus dan teruji.

Keuntungan

  • Struktur yang konsisten. Sangat berguna bila developer banyak dan turnover tinggi.
  • Struktur merupakan best practices. Semua sudah ditempatkan di tempat yang paling sesuai.
  • Dapat belajar tentang desain aplikasi yang baik.

Kerugian

  • Butuh investasi waktu belajar dan adaptasi
  • Ada overhead. Untuk project sangat kecil, mungkin overheadnya lebih besar dari projectnya sendiri. Lagipula, tidak semua fitur framework kita pakai, sehingga cuma akan menjadi bloat.
  • Menimbulkan dependensi. Ini terutama terasa di aplikasi yang berarsitektur plugin. Upgrade framework dapat merusak plugin.

Memilih Framework

Sekarang, bagaimana kita memutuskan pakai framework atau tidak? Kalau pakai, pilih yang mana? Sering sekali ada banyak framework yang menyelesaikan masalah yang sama.

Pertama, pertimbangkan benefit vs cost. Di beberapa project, saya lebih memilih tanpa framework, karena ukuran projectnya kecil.

Untuk playbilling, saya pakai iBatis alih-alih Hibernate yang lebih lengkap fiturnya. Pertimbangannya adalah, saya tidak menggunakan banyak tipe database. Sehingga cross-database tidak terlalu dibutuhkan. Sekarang saya sedang mempertimbangkan menghilangkan iBatis, dan pakai JDBC biasa untuk mengurangi dependensi dan ukuran donlod.

Kedua, lihat kualitas dokumentasinya. Alasan yang jelas adalah, kalau tidak ada dokumentasi, gimana tau cara pakainya? Kita butuh dokumentasi untuk bisa menggunakan framework.

Ada alasan kedua yang juga penting. Kualitas dokumentasi mencerminkan kualitas framework. Mengapa? Karena dokumentasi biasanya adalah by product (produk sampingan), apalagi di project open source. Logikanya, jika tim developer menghasilkan dokumentasi bagus, pasti kualitas dan desain frameworknya sendiri lebih bagus lagi.

Sejauh ini, kesimpulan saya konsisten. Framework terbaik secara desain dan kualitas kode adalah Spring Framework. Coba lihat dokumentasinya. Sangat rinci, detail, dan minim kesalahan. Contoh lain adalah Hibernate. Dokumentasinya sangat lengkap. Bahkan di dalamnya juga dijelaskan tentang konsep Object Relational Mapping. Dengan membaca dokumentasinya saja, kita akan menambah wawasan. Apalagi menggunakan frameworknya.

Ketiga, lihat aktivitas komunitasnya. Framework, apalagi open source, membutuhkan interaksi dengan sesama pengguna. Keuntungan utama tentu saja technical support dan tutorial gratis. Apalagi dengan perkembangan blog yang sangat pesat beberapa tahun terakhir. Semua pengalaman baik, buruk, mudah, sulit, semua diceritakan para pengguna framework di blognya masing-masing.

Kalau kita menggunakan framework minoritas, jarang digunakan orang, tutorialnya sedikit, diskusi di berbagai forum juga tidak banyak. Jadi, kalau kita search dengan Google, lebih sulit menemukan permasalahan (dan solusi) yang sama dengan kebutuhan kita.

Terakhir, learning curve, atau kurva belajar. Apakah framework tersebut sulit atau mudah dipelajari?

Di bagian atas tadi saya menyebutkan keunggulan framework adalah dia dapat menyeragamkan struktur kode di antara banyak developer. Jadi, agar efektif, semua developer harus bisa menggunakan framework tersebut.

Nah, seorang system architect, software designer, senior developer, development team leader, atau apapun istilahnya di tempat Anda, orang yang bertugas memilih framework, harus mempertimbangkan kurva belajar ini.

Ini sering diabaikan banyak orang. Sebagai pemilih framework, tentunya orang tersebut memiliki keahlian/pengalaman teknis di atas rekan-rekannya. Penting bagi orang tersebut untuk memperhitungkan keahlian/pengalaman anggota tim yang lain yang tidak secanggih dirinya pada waktu memilih framework. Jangan sampai framework yang dipilih terlalu rumit, sehingga bukannya di-reuse malahan di-abuse.

Demikian ulasan singkat tentang framework. Mudah-mudahan bermanfaat.


Bisnis Open Source

Artikel ini, tidak seperti biasanya, ditulis berdasarkan request oleh teman saya. Selain itu, juga ada thread di milis JUG Indonesia yang membahas tentang bisnis open source. Di sana saya memberikan sedikit komentar yang secara singkat serupa dengan apa yang akan dijelaskan di sini.

Beberapa tahun belakangan ini, gema open source mulai ramai di dunia. Banyak orang yang tadinya skeptis dengan ide software gratis, mulai mencoba peruntungannya di dunia yang buka-bukaan ini. Banyak juga orang (salah satunya saya) yang bergembira dan sangat mendukung open source, terutama karena ke’gratis’annya semata.

Tidak kurang dari perusahaan besar di dunia seperti Oracle, IBM, Sun, dan masih banyak yang lainnya, merilis aplikasi mereka yang berharga jutaan dolar secara open source atau ‘gratis’.

Open source tidak selalu gratis, walaupun biasanya begitu. Dan gratis juga tidak selalu berarti open-source. Untuk menyederhanakan urusan, yang akan kita bahas di sini adalah software gratis. Terlepas dari apakah software tersebut open source atau tidak.

Orang-orang pun mulai bertanya, “Apa tidak rugi melepas aplikasi secara gratis? Dari mana keuntungannya? Padahal untuk membuat software tersebut, telah banyak biaya yang dikeluarkan.” Dan masih banyak lagi pertanyaan sejenis.

Tapi yang jelas, mereka tidak menjadi rugi karena melepas aplikasinya. Tindakan ini tentunya sudah didahului dengan kalkulasi bisnis yang matang dan tidak semata ikut-ikutan trend open source atau tiba-tiba menjadi ‘baik hati’ terhadap negara ketiga/miskin (misalnya, Indonesia). Nah, sekarang mari kita lihat, dari mana profitnya.

Setidaknya ada beberapa modus operandi penggunaan strategi gratis untuk perusahaan, sepanjang pengetahuan saya:

  1. RND
  2. Teaser product
  3. Strategi Produk Komplementer
  4. By product
  5. Pendukung core business
  6. Sebagai produk utama

Mari kita lihat satu per satu.

Disclaimer: semua yang saya tulis di sini merupakan pendapat pribadi saya, atas pengamatan tentang penggunaan strategi gratisan, yang tidak terbukti kebenarannya. Tidak ada pernyataan resmi dari perusahaan yang disebut di sini tentang strategi gratisnya. Silahkan tulis komentar anda di bawah kalau setuju/tidak setuju dengan pendapat saya ini.

Research and Development

Strategi ini digunakan oleh RedHat. Mereka membuat project open source Fedora sebagai lini depan riset Linux. Teknologi yang dihasilkan di project Fedora kemudian digunakan di lini produk komersilnya Red Hat Enterprise Linux. Dengan menggunakan project open source sebagai divisi RND, Red Hat mendapat keuntungan dari kontribusi tenaga kerja gratisan (baca: sukarelawan) baik di posisi developer, tester, dokumenter, public relation (dalam bentuk komentar positif, testimoni, word of mouth), dan juga technical writer (blog membahas penggunaan Fedora, support forum, mailing list, dsb). Seperti kita lihat di sini, sebenarnya Red Hat mendapat keuntungan besar, setidaknya dari sisi payroll dan marketing, dengan menggunakan strategi open source.

Latihan buat pembaca, sebutkan contoh lain perusahaan yang menggunakan open source sebagai divisi RND.

Teaser Product

Promosi produk yang terbaik adalah dengan cara memberikan produk tersebut ke konsumen, dan berharap mereka puas dan bercerita kepada teman-temannya (yang diharapkan akan membeli produk tersebut). Strategi ini digunakan Oracle pada saat mereka melepas produk Oracle 10g Express Edition. Harapannya adalah, dengan menggunakan produk gratis tersebut:

  1. Lebih banyak orang yang familiar dengan produk Oracle
  2. Pengguna merasa puas atau sudah terlalu terbiasa (baca: kecanduan) dengan Oracle
  3. Pada suatu saat, pengguna gratisan tersebut merasa kurang dengan fitur yang ada, dan akan membeli versi berbayarnya
  4. Jika pengguna gratisan diminta rekomendasi oleh bosnya/temannya, mereka akan merekomendasikan Oracle, karena itulah produk yang mereka kuasai, dan lagipula bukan mereka yang akan membayarnya.

Strategi pemasaran ini lebih efektif daripada memasang iklan di media. Banyak orang (termasuk saya) yang sudah sangat bosan dengan iklan, sehingga ada fitur ‘autoskip’ di otak saya yang secara otomatis menutup popup iklan, bahkan sebelum gambarnya selesai loading. Bahkan untuk kasus ekstrim, banyak orang mau bersusah payah yang memasang filter iklan seperti Adblock atau no-ads.pac untuk melucuti media dari semua iklan.

Dengan menggunakan ‘orang betulan’ yang tulus dan jujur untuk merekomendasikan produknya, lebih besar kemungkinan produk akan dibeli.

Strategi Produk Komplementer

Ada kalanya perusahaan menggratiskan suatu aplikasi karena aplikasi tersebut adalah komplementer dari produk utamanya. Contohnya adalah Acrobat Reader.

Waktu kita belajar di SMP dulu, kita belajar tentang produk substitusi dan komplementer. Produk substitusi adalah produk yang dapat menggantikan produk lain. Misalnya, Indomie adalah produk substitusi Mi Sedap.

Sedangkan produk komplementer adalah produk yang saling melengkapi dengan produk lain. Seperti yang sering kita lihat di tivi, salah satu iklan tag linenya adalah, “Apapun makanannya, minumnya tetap … (produk XXX)”. Nampaknya produsen minuman tersebut berusaha serakah dengan menjadikan produknya sebagai komplementer untuk semua makanan padat.

Acrobat Reader, adalah komplementer dari Acrobat Distiller. Dengan menggratiskan Reader, Adobe berharap penjualan Distiller akan meningkat. Sepertinya strategi ini cukup jitu, sehingga PDF bisa jadi standar format dokumen di internet.

Lebih lanjut tentang penggunaan strategi produk komplementer ini dijelaskan oleh Joel Spolsky. Silahkan baca sendiri di websitenya.

By Products

By products artinya produk sampingan. Misalnya kita membuka usaha jualan kelapa parut di pasar, kita akan mendapatkan banyak sekali air kelapa sebagai limbah. Mereka yang jeli akan segera beternak jamur di dalam air kelapa tersebut dan segera membuka lini produk baru, yang lebih tenar disebut dengan Nata de Coco.

Hal yang sama dilakukan oleh Martin Fowler dan gerombolannya. Bisnis utama mereka adalah software development dan konsultasi bagi perusahaan software development yang lainnya. Sebagai mana konsultan manajemen pada umumnya, mereka juga berjualan jargon. Salah satu jargon yang mereka perdagangkan adalah Continuous Integration. Ini tidak lain adalah istilah keren dari kompile sering-sering dan test sampai capek. Menyuruh programmer kompile lima kali sehari dan testing sepuluh kali sehari kemudian menulis hasilnya dalam format HTML adalah cara cepat untuk membuat programmer pensiun dini alias resign. Oleh karena itu, mereka membuat program kecil yang bisa melakukan kegiatan tersebut secara terjadwal dan terus menerus. Sehingga jargon Continuous Integration bisa dijual dengan sukses.

Program kecil tersebut adalah Cruise Control. Dapat Anda peroleh secara gratis di SourceForge.

Perhatikan di sini bahwa dagangan utama mereka adalah proses, bukan produk. Sehingga Cruise Control tersebut adalah by product belaka. Sama seperti ‘nata de coco’. Karena bukan produk utama, tidak ada kerugian dari melepas aplikasi tersebut secara gratis. Keuntungannya, para calon prospek akan berpersepsi bahwa Martin Fowler masih punya mainan lain yang lebih menarik yang tidak digratiskan. Sehingga dengan senang hati mereka akan mempekerjakan dia dan pasukan magangnya dengan tarif selangit.

Pendukung produk utama

Framework favorit saya, Spring Framework adalah contohnya. Produk utama Interface 21, perusahaan sponsor Spring Framework, adalah perusahaan software development. Berbagai perusahaan besar di dunia mempercayakan pengembangan aplikasi bisnisnya pada Interface 21. Jadi, produk utama Interface 21 adalah software development. Dalam mengembangkan aplikasi pesanan client, Interface 21 membutuhkan framework berkualitas tinggi dan berarsitektur bagus. Di situlah peranan project Spring Framework, sebagai produk pendukung aktivitas bisnis Interface 21.

Produk Utama

Ada juga beberapa perusahaan yang menjadikan aplikasi gratisnya sebagai produk utama. Lalu datang pertanyaan, “Kalau produk utama digratiskan, dari mana dapat uangnya?”. Ada beberapa jalur lain di luar penjualan software: training, buku, dan customization. Jalur ini ditempuh JBoss dan Hibernate. Dokumentasi utama JBoss tidak gratis. Kita harus membeli dengan sistem berlangganan di websitenya.

Hibernate, mendapat pemasukan dari penjualan buku. Pembuatnya, Gavin King dan Christian Bauer mengarang buku yang bagus sekali, Hibernate in Action. Isinya menjelaskan desain aplikasi pada umumnya, dan penggunaan framework Hibernate. Dengan semakin banyaknya pengguna Hibernate, buku dan training akan semakin laku.

PlaySMS dan PlayBilling, mendapat pemasukan dari customization. Para pelanggan seringkali membutuhkan fitur khusus yang belum ada di rilis open source. Untuk itu, mereka membayar developer untuk menambahkan fitur yang dibutuhkan. Siapa yang lagi yang lebih berkompeten menulis tambahan fitur selain pengembang aslinya?

Demikianlah uraian tentang bisnis open source. Jadi, hilangkan ilusi bahwa perusahaan besar sekarang menjadi dermawan, karena memberikan aplikasinya secara gratis. Ada kepentingan pemegang saham di baliknya, yang tentu saja, tidak mau rugi.

Walaupun demikian, kita lihat ada situasi win-win di sini. Pengguna diuntungkan dengan adanya software gratis. Perusahaan juga diuntungkan dari promosi gratis, tenaga sukarela, dan berbagai keuntungan lainnya.

Oleh karena itu, mari gunakan aplikasi gratis. Kalo bisa gratis, kenapa harus bayar? Kalo ada yang gratis, kenapa masih membajak?

:D


Ruthless Testing 3

Alkisah, di suatu project, ada kode program yang berkelakuan aneh. Kode program tersebut berfungsi untuk melakukan pendaftaran user baru ke dalam sistem. Jadi, user membuka form, mengisi data diri, dan menekan tombol Submit. Tidak ada yang aneh dengan fiturnya.

Keanehannya adalah, entah kenapa, aplikasi tersebut cuma bisa digunakan 7 kali. Jadi pada waktu user ke-8 menekan tombol Submit, datanya tidak tersimpan di database. Anehnya juga, aplikasi tidak menimbulkan pesan error. Hmm … sungguh gaib.

Berbagai upaya dilakukan untuk mengatasi masalah ini. Tim pengusir hantu didatangkan, lengkap dengan kostum putih-putih dan botol penangkap hantu, karena dicurigai ada ‘sesuatu’ dengan angka 7. Tetapi tidak juga mencapai solusi yang memuaskan.

Akhirnya, seorang anggota milis JUG didatangkan. Beliau memeriksa source code fitur registrasi tersebut, sebagai berikut:

public void save (User u) {
  try {
    Connection conn = DriverManager.getConnection(url, username, password);
    
    PreparedStatement pstm = conn.prepareStatement("INSERT INTO user VALUES (?,?,?)");
    pstm.setInt(1, u.getId());
    pstm.setString(2, u.getUsername());
    pstm.setString(3, u.getPassword());
    
    pstm.executeUpdate();
  } catch(Exception err) {

  }
}

Pembaca yang teliti (ya, maksudnya Anda) akan segera menemukan asal muasal semua ‘kejadian gaib’ di atas, yaitu:

  1. Connection dibuka, tapi tidak pernah ditutup. Besar kemungkinan max connection di database adalah 7 concurrent connection. Sehingga setelah 7 kali connect dan 0 kali disconnect, database akan menolak koneksi baru.

  2. Catch block dibiarkan kosong, sehingga error dari database tidak akan tampil di mana-mana.

Hmm .. kesalahan yang ‘newbie banget’. Melalui pemeriksaan menyeluruh, ditemukan kesalahan serupa di berbagai bagian kode yang lain.

Pada titik ini, para project manager, development team leader akan segera mengeluh dan bersiap-siap mengisi komentar di bawah, “Masa saya harus baca kode baris-per-baris? Kayak kurang kerjaan aja !!” Sebelum Anda lakukan itu, sabar dulu .. baca sampai habis. Kita akan segera lihat solusinya.

Pemeriksaan baris kode seperti ini sangat melelahkan. Semakin besar projectnya, semakin banyak baris kodenya, semakin tinggi beban pemeriksaannya. Di lain pihak, kalau kita tidak melakukan pemeriksaan, kita menimbulkan resiko terjadinya masalah di kemudian hari.

Jadi, bagaimana solusinya?

Untungnya –seperti biasa– kita bukan yang pertama menemukan masalah seperti ini. Masalah sudah pernah dialami orang lain, dan dibuatkan solusinya, sehingga kita –seperti biasa– tinggal download dan pakai :D

Jawaban dari masalah ini adalah automated code review. Tools ini akan melakukan review terhadap source code, sesuai dengan aturan yang kita tetapkan, dengan teliti, otomatis, dan repeatable. Dengan tool ini, berapapun baris kode yang ada, semua akan diperiksa secara menyeluruh.

Ada beberapa solusi yang dapat digunakan:

Pada contoh kali ini, kita akan coba menggunakan PMD. Caranya mudah:

  1. Download dari websitenya.

  2. Extract

  3. Buat target di Ant untuk memanggil PMD.

  4. Lihat reportnya

Untuk langkah #1 dan #2 tidak perlu dijelaskan lebih lanjut. Target Ant untuk langkah #3 adalah sebagai berikut:

<target name="code-review" depends="prepare">
  <pmd targetjdk="1.5" shortFilenames="true">
   
    <ruleset>basic</ruleset>   
    <ruleset>codesize</ruleset>
    <ruleset>clone</ruleset>
    <ruleset>controversial</ruleset>
    <ruleset>coupling</ruleset>
    <ruleset>design</ruleset>
    <ruleset>finalizers</ruleset>
    <ruleset>imports</ruleset>
    <ruleset>javabeans</ruleset>
    <ruleset>logging-java</ruleset>
    <ruleset>logging-jakarta-commons</ruleset>
    <ruleset>naming</ruleset>
    <ruleset>optimizations</ruleset>
    <ruleset>strictexception</ruleset>
    <ruleset>strings</ruleset>
    <ruleset>sunsecure</ruleset>
    <ruleset>unusedcode</ruleset>
   
    <formatter
        type="net.sourceforge.pmd.renderers.HTMLRenderer"  
        toFile="${pmd.result}/pmd.html"
    />
    <fileset dir="src">
      <include name="**/*.java"/>
    </fileset>
  </pmd>
</target>

Berikut penjelasannya:

  1. Target JDK : memeriksa kesesuaian dengan JDK 1.5

  2. Ruleset : Aturan yang akan diberlakulkan. Detailnya bisa dilihat di website PMD. Sebagai contoh, dengan memberlakukan ruleset basic, kita memeriksa blok catch yang kosong, sehingga mencegah masalah pesan error di atas. Sedangkan ruleset design memeriksa apakah Connection yang dibuat sudah ditutup.

  3. Formatter : Jenis formatter yang digunakan. Report yang dihasilkan PMD dapat berupa text, xml, csv.

  4. Fileset: source code yang akan direview. Kita dapat mengganti parameter ini dan mereview semua source code yang ada di harddisk kita. SIlahkan mencoba mendownload source code project open source java (misalnya Tomcat, atau JBoss), dan lihat apakah kode programnya ditulis dengan baik.

Laporan yang dihasilkan bentuknya seperti ini: PMD Review Result

Selamat mencoba. Semoga bermanfaat.


Cost of Quality

Mumpung sedang hangat membahas testing, coba kita dengarkan apa pendapat manajemen.

Programmer [P] : Bos, kata Mr. Endy, kita harus bikin unit test, integration test, coverage test dsb Manager [M] : Stop, banyak sekali testnya? Memangnya kamu gak bisa bikin kode yang bener, sampe ditest segitu banyaknya? [P] : Ya bisa bos, tapi .. [M] : Ya sudah kalo bisa coding sana yang bener, test nanti saja waktu sudah delivery. Kita sudah mepet deadline ini. Kita dibayar bukan untuk coding unit test. [P] : (kecewa, cuma bisa gigit mouse) Ya deh bos …

Umumnya, begitulah tanggapan pihak manajemen dalam menyikapi test. Test dianggap sebagai kegiatan yang (walaupun) penting, prioritasnya ada di kelas ekonomi. Saya sendiri, walaupun merupakan penggemar unit testing dan percaya akan manfaatnya, kadang merasa tidak pede untuk berargumen dengan manajemen tentang urusan ini.

Sampai suatu hari, ada training di kantor tentang Software Engineering. Instrukturnya adalah konsultan manajemen yang ahli di bidang ISO dan CMMI.

Biasanya, saya rada skeptis dengan yang namanya konsultan manajemen. Baik itu konsultan pemasaran, konsultan ISO, atau bidang manajemen yang lainnya. Kebanyakan dari mereka (tidak semua, tapi kebanyakan) biasanya cuma bisnis jargon saja. Cari uang dari menciptakan jargon aneh, menjelaskan jargon tersebut, dan menyuruh kita menggunakan jargon tersebut. Selebihnya nasihatnya mirip-mirip ramalan bintang, nasihat yang buram dan bisa ditafsirkan apa saja.

Tapi kali ini, sang konsultan mengetengahkan jargon yang cukup menarik, yaitu Cost of Quality. Berikut penjelasannya.

Biasanya, dalam mengerjakan project software, kegiatan apa yang ada di project schedule kita? Umumnya seperti ini:

  1. Analisa : membuat spesifikasi requirement user
  2. Desain : desain tampilan dan arsitektur aplikasi
  3. Coding
  4. User Testing
  5. Implementasi : migrasi data, training user, tuning
  6. Garansi
  7. Makan-makan (kalo ada profit)

Si konsultan bilang, memang itu semua (1-6) adalah kegiatan utama. Tanpa kegiatan itu, project tidak bisa diutamakan. Tapi, dengan 6 aktifitas tersebut, kecil peluangnya kita akan sampai ke aktivitas #7, yaitu makan-makan.

“Kenapa begitu ?”, demikian para peserta training bertanya dengan antusias, nampaknya jelas kalau urusannya menyangkut perut (tidak jadi makan-makan) orang ngantuk bisa langsung jadi segar.

“Ya sebab di sana belum dianggarkan Biaya Kualitas (Cost of Quality), nantinya kualitas rendah, banyak perbaikan, sehingga profit terancam tergusur”, jawab instruktur.

Nah, sekarang apa saja biaya kualitas itu? Diantaranya adalah:

  1. Training : memastikan pekerjaan tidak dikerjakan secara trial and error

  2. Review : mendeteksi kesalahan sedini mungkin. Kesalahan desain bisa diperbaiki dalam beberapa halaman dokumen desain. Tetapi jika dibiarkan sampai coding, banyak sekali effort untuk debug dan bugfix yang harus dikeluarkan. Misal: mengganti iBatis dengan Hibernate di dokumen desain cukup dengan Find and Replace. Mengganti iBatis dengan Hibernate di kode program? Bayangkan sendiri.

  3. Rework : harus ada anggaran untuk melakukan perbaikan dokumen, bugfix, dsb

  4. Audit : sebelum hasil pekerjaan dideliver ke client, harus diperiksa dulu secara internal. Audit proses juga dilakukan untuk memastikan semua Cost of Quality sudah diperhitungkan dan dijalankan.

  5. Testing : testing sebanyak mungkin dan seawal mungkin.

Dalam project software, kita mengenal fenomena bola salju. Tadinya kecil, menggelinding menjadi besar sehingga dapat menggulung satu desa (seperti di film kartun). Di software sama. Kita ingin mendeteksi kesalahan sedini mungkin, kalau bisa di tahap analisa semua kesalahan sudah dieliminasi, sehingga tidak merembet ke kode program. Jadi, perlu ada review dan audit untuk memastikan kesalahan tidak ditemukan di fase-fase akhir. Karena memperbaiki kesalahan di awal (requirement dan design) jauh lebih murah daripada di akhir (kode program, materi user training, user manual, dan script migrasi data).

Baiklah, cost of quality itu penting. Sekarang bagaimana cara menjelaskan pada manajemen mengenai tambahan biaya tersebut?

Mari kita rekonstruksi dialog Programmer dan Manager.

Programmer [P] : Bos, kata Mr. Endy, kita harus bikin unit test, integration test, coverage test … Manager [M] : Stop, banyak sekali testnya? Memangnya kamu gak bisa bikin kode yang bener, sampe ditest segitu banyaknya? [P] : Ya bisa bos, tapi .. [M] : Ya sudah kalo bisa coding sana yang bener, test nanti saja waktu sudah delivery. Kita sudah mepet deadline ini. Kita dibayar bukan untuk coding unit test. [P] : Memangnya kalo boleh tau, seperti apa jadwalnya Bos? [M] : Kamu programmer mau tau saja. Tapi gpp, karena ini percakapan boongan baiklah akan saya kasi tau:

  1. Analisa : 2 minggu
  2. Desain : 1 minggu
  3. Coding : 4 minggu
  4. User Testing dan Bugfix : 4 minggu
  5. Implementasi : 4 minggu
  6. Garansi : 8 minggu Total : 23 minggu

[P] : Kenapa User Testing dan Implementasi lama sekali Bos? Sama lamanya dengan Coding? [M] : Ya itu karena kamu dan teman-temanmu kerjanya salah melulu, jadi di User Testing dan Implementasi banyak masalah.

[P] : Bagaimana kalau saya usul jadwal seperti ini :

  1. Analisa : 2 minggu
  2. Review dan rework : 1 minggu
  3. Desain : 1 minggu
  4. Review dan rework : 1 minggu
  5. Training : 1 minggu
  6. Coding + Unit Testing: 6 minggu
  7. User Testing dan Bugfix: 2 minggu
  8. Implementasi : 1 minggu
  9. Garansi : 8 minggu Total : 23 minggu Sama kan Bos, total waktunya. Saya yakin dengan tambahan aktifitas review, rework, dan training, kita akan bisa tangkap sebagian besar bug sebelum User Testing. Dengan demikian, bug yang terlihat sama user tinggal sedikit karena sudah kita temukan duluan. Kalau sebelum coding kita ditraining dulu, codingnya bisa lebih cepat dan bener Bos, sehingga bugnya lebih sedikit. Mudah-mudahan client jadi puas.

[M] : Wah pintar juga kamu, di rumah dikasi makan apa sama Emaknya bisa pintar gini? Baiklah akan saya coba usul kamu.

Demikianlah, cost of quality itu penting. Lebih penting lagi adalah cara kita menjual pada manajemen, supaya kegiatan testing dan training tidak dianggap sebagai kegiatan ‘buang-buang uang’ dan ‘tidak dibayar client’. Sebenarnya, client membayar untuk mendapat hasil yang berkualitas dan memuaskan. Secara tidak langsung, mereka membayar kita untuk melakukan testing.

Referensi : Software Quality at Top Speed


Ruthless Testing 2

Pada artikel sebelumnya, kita telah membahas tentang penggunaan unit test dan integration test sederhana menggunakan DBUnit. Pada artikel kali ini, kita akan membahas tentang coverage testing

Sebagai technical leader, project manager -atau apapun nama jabatannya- yang bertugas mengawasi segerombolan programmer, bagaimana cara kita memastikan bahwa mereka membuat unit test untuk setiap kode yang ditulis?

Cara manual tentu saja dengan memeriksa unit test satu-persatu dan membandingkannya dengan kode program aplikasi. Kita cocokkan tiap unit test dengan pasangan kode yang ditest. Dengan demikian, kita tahu mana kode yang sudah ditest mana yang belum.

Sayangnya, cara ini tidak otomatis. Sehingga kalau nanti dihadapkan pada deadline ketat, dipastikan kegiatan ini akan segera diabaikan. Oleh karena itu kita harus mengotomasi pemeriksaan test ini sehingga di tengah tekanan jadwal, kita tetap bisa memastikan unit test dibuat dengan benar.

Ada beberapa tools yang beredar di pasaran untuk mengotomasi pemeriksaan ini, diantaranya:

Semua tools di atas melakukan ‘coverage testing’, yaitu pengetesan apakah unit test yang dibuat telah meng-cover semua kode yang ditest. Jika unit testnya terlalu sedikit, maka coverage testing akan failed.

Pada contoh kali ini, kita akan menggunakan Cobertura. Cobertura mampu memeriksa coverage terhadap baris kode dan percabangan. Jadi kalau ada percabangan (if-else, switch) yang belum ditest, cobertura akan melaporkan. Kalau ada baris kode yang belum terjangkau unit test, cobertura juga akan memperingatkan.

Sebagai supervisor, kita dapat menetapkan aturan pada project. Misalnya, “Untuk project ini, saya ingin test meng-cover minimal 70% dari seluruh baris dan 90% dari seluruh percabangan”.

Bagaimana cara Cobertura melakukan keajaiban ini? Jawabannya, melalui mekanisme yang disebut code instrumentation. Cobertura akan memodifikasi bytecode (*.class) yang dihasilkan oleh proses kompilasi. Bytecode yang dihasilkan javac akan ditambah dengan kode-kode khusus untuk menghitung dan mendeteksi invokasi. Dengan demikian, pada saat unit test dijalankan, Cobertura akan mengetahui unit test yang mana menjalankan kode program yang mana. Bytecode yang akan diproses oleh Cobertura harus dikompile dengan flag -debug.

Dengan demikian, untuk menjalankan Cobertura, kita membutuhkan dua kali tahap kompilasi. Kompilasi pertama mengubah *.java menjadi *.class. Kompilasi kedua menambahkan instrumen di *.class.

Berikut adalah Ant target untuk melakukan instrumentasi.

<target name="instrument-cobertura" depends="compile-cobertura">        
        <!--
                Instrument the application classes, writing the
                instrumented classes into ${build.instrumented.dir}.
        -->        
        <cobertura-instrument todir="${compile.cobertura}">			
			<includeClasses regex=".*" />
			<excludeClasses regex=".*\Test.*" />  
			<instrumentationClasspath>
				<pathelement location="${compile.debug}" />
			</instrumentationClasspath>
        </cobertura-instrument>
    </target>

Selanjutnya, kita menjalankan unit test seperti biasa (melalui Ant target). Bedanya adalah, kita menggunakan hasil kompilasi Cobertura. Ant target untuk menjalankan unit test adalah sebagai berikut:

<target name="unit-test" depends="instrument-cobertura">
        <junit haltonfailure="false" fork="yes">            
            <classpath location="${compile.cobertura}"/>
            <classpath refid="cobertura-classpath"/>
            <formatter type="xml"/>
            <batchtest todir="${junit.result}">
                <fileset dir="${compile.debug}" includes="**/*Test.class"/>
            </batchtest>
        </junit>
    </target>

Perhatikan referensi ke ${compile.cobertura} yang diletakkan di atas referensi cobertura-classpath. Ini mengisyaratkan bahwa class hasil instrumentasi Cobertura diload lebih dulu daripada class yang dikompilasi secara normal.

Terakhir, kita buat Ant target untuk memeriksa coverage dan menghasilkan HTML report.

<target name="coverage-test" depends="unit-test">
        <cobertura-check datafile="cobertura.ser" 
                         branchrate="70" 
                         linerate="90"
                         haltonfailure="false"
        />
        <cobertura-report datafile="cobertura.ser"
                          srcdir="src" destdir="${cobertura.result}"
        />
    </target>

Perhatikan nilai batas baris (linerate) dan percabangan (branchrate) yang harus ditest. Nilainya sudah disesuaikan dengan aturan yang kita tetapkan di atas, yaitu sebesar 70% dan 90%.

Misalnya kita memiliki class DayCounter.java sebagai berikut:

public class DayCounter {
    public int numDays(int month, int year){
        switch (month) {
            case 1: 
            case 3:
            case 5: 
            case 7: 
            case 8:
            case 10:
            case 12: return 31;
            case 4: 
            case 6:
            case 9: 
            case 11: return 30;
            case 2: 
                if (year%4 == 0) {
                    return 29;
                } else {
                    return 28;
                }
            default: return 0;
        }
    }
} 

Dan unit testnya DayCounterTest.java sebagai berikut:

package tutorial.testframework;

import junit.framework.TestCase;

public class DayCounterTest extends TestCase {
    public void testNumDays() {
        DayCounter d = new DayCounter();
        assertEquals(31, d.numDays(12,2001));        
        assertEquals(30, d.numDays(11,2001));
        assertEquals(28, d.numDays(2,2001));
        assertEquals(29, d.numDays(2,2000));
        assertEquals(0, d.numDays(21,2000));
    }
}

Akan menghasilkan coverage yang bagus, karena semua baris sudah ditest. Berikut adalah hasil coverage testnya:

Cobertura All Pass

Kita juga bisa melihat coverage detail dari class DayCounter.java:

Cobertura Class Detail Pass

Bila kita non-aktifkan beberapa test, seperti ini:

package tutorial.testframework;

import junit.framework.TestCase;

public class DayCounterTest extends TestCase {
    public void testNumDays() {
        DayCounter d = new DayCounter();
        assertEquals(31, d.numDays(12,2001));        
        assertEquals(30, d.numDays(11,2001));
        //assertEquals(28, d.numDays(2,2001));
        //assertEquals(29, d.numDays(2,2000));
        //assertEquals(0, d.numDays(21,2000));
    }
}

Maka kode kita tidak akan lolos test, karena hasil coverage totalnya seperti ini:

Cobertura All Failed

dan detail classnya seperti ini

Cobertura Class Detail Failed

Bagaimana? Mudah dan cepat kan? Dengan cara ini, kita dapat mendeteksi tingkat kemalasan programmer dalam membuat unit test. Pada artikel selanjutnya, kita akan membahas tentang code-compliance test. Test ini sering juga disebut code-review.