Saturday, February 26, 2005

Inductive User Interface

Inductive User Interface (IUI) diperkenalkan Microsoft, lihat disini artikel lengkapnya, katanya IUI adalah model user interface baru yang menyarankan bagaimana membuat aplikasi-aplikasi software menjadi lebih sederhana dengan memecah menjadi beberapa screen atau halaman sehingga mudah dijelaskan dan dimengerti.

IUI bisa dibilang lebih seperti web-sytle application karena merupakan desain interface yang fokus pada single task (satu pekerjaan) sehingga memudahkan user untuk mengetahui apa yang harus dilakukan dan apa yang dilakukan selanjutnya. Hmm.. pasti kita berfikir ini seperti wizard ya?

IUI design guidelines meliputi :
  1. Setiap screen fokus pada satu pekerjaan.
  2. Jelaskan atau deskripsikan pekerjaan tersebut. Gunakan judul yang baik/mudah jika perlu berikan deskripsi tentang pekerjaan pada screen tersebut.
  3. Buat bagian-bagian yang mengisi screen nyaman untuk pekerjaan tersebut. Pilih control/komponen yang tepat.
  4. Berikan link ke pekerjaan berikutnya
Menurut saya, dilihat dari contoh-contohnya desain IUI memang sangat mirip dengan web application, terutama dari segi artistik, penempetan menu dan deskripsi dari suatu task dalam satu halaman. Karena lebih artistik dibanding desain widget/window desktop yang biasa, IUI lebih menarik untuk dilihat.

Tapi apakah kemudahan menjadi salah satu tujuan utama desain UI? Salah satu aspek yang tidak kalah penting adalah aspek produktifitas. Komentar Inductive vs Productive UIs membuka mata kita juga bahwa produktifitas penggunaan aplikasi adalah penting juga selain kemudahan.

Lihat komentar selajutnya dari penulis artikel IUI tersebut.

Code Coverage: Seberapa menyeluruh tes yang dilakukan?

Setelah kita melakukan unit test pada kode program kita, akan timbul perasaan percaya diri jika test yang kita lakukan berhasil (sukses) semua. Tapi muncul pertanyaan, apa unit test yang kita buat sudah menyeluruh sehingga kemungkinan untuk error (adanya bug) kecil sekali?

Pengenalan tentang code coverage bisa dibaca disini atau baca artikel yang agak detail "Introduction to Code Coverage" . Berapa artikel tentang code coverage dan detail teknik pengecekan coverage tool bisa didapatkan di halaman ini.

Code coverage, secara sederhana dapat dikatakan sebagai pengukuran terhadap hasil tes yang telah dilakukan. Seberapa menyeluruh? Apakah ada kode yang belum ditest? Nah, code coverage menjawab pertanyaan2 itu. Dengan code coverage tool yaitu software untuk membantu secara otomatis melakukan code coverage, kita akan mendapatkan summary dari analisis seberapa baik atau mnyeluruhnya test yang kita lakukan. Code coverage tool melakukan tes pada kode program kemudian membandingkannya dengan tes yang telah kita lakukan. Beberapa metode dilakukan oleh tool untuk mengecek apakah suatu statement, blok, fungsi atau methode sudah dites atau belum. Beberapa metode yang umum dilakukan oleh code coverage diantaranya:
  • Statement coverage/line coverage,
  • Basic block coverage,
  • Decision coverage/branch coverage
  • Condition coverage
  • Multiple condition coverage
  • Path coverage
  • Function coverage
  • Relational operator coverage
Artikel lain yang bagus, banyak menjelaskan metode-metode yang pengukuran dapat dibaca di artikel Code Coverage Analysis.

Kesimpulannya, coverage tool hanya sebatas tool, 100% coverage dari hasil analisis tool merupakan persentase menyeluruhnya sangatlah relatif. Tentu saja masih diperlukan critical thinking dalam mengalisis kode program kita, mensimulasikan kemungkinan2 error dan masih perlu test lain seperti performance testing.


Di artikel "Java Code Coverage Tools Evaluation" kita bisa baca evaluasi beberapa java coverage tool, dan kesimpulan pada artikel tersebut Emma and Clover adalah yang terbaik diantara yang lain.

Lihat juga list coverage tool open source untuk Java

Friday, February 25, 2005

CVS statistik report

StatCVS berguna untuk membuat report HTML dari CVS repository. Kita dapat melihat grafik-grafik statistik aktifitas pada repository, seperti:
  • Grafik lines of code (LOC) per-waktu
  • Persentase LOC per-author
  • Repository-directory/package tree
  • LOC dari masing-masing repository-directory/package
  • LOC per-author per-waktu
  • Rangkuman aktivitas (commits) per-jam dalam sehari
  • Rangkuman aktivitas (commits) per-hari dalam seminggu
  • Aktifitas (commits) masing-masing author per-tanggal
  • perbandingan modifying vs Adding dari masing-masing author
  • Juga dapat diintegrasikan dengan program CVS viewer/browser seperti : viewCVS, cvsweb, atau Chora

Download cvsnt dari http://cvsnt.org lalu install
Download statcvs dari http://statcvs.sourceforge.net

Misalkan user cvs adalah ejlp dan CVS server kita adalah 3.219.189.99 dengan repository path-nya adalah C:/project

Login ke CVS server

D:\myproject1>cvs -d:pserver:ejlp@3.219.189.99:C:/project login

Check out project dari CVS server

D:\myproject1>cvs -d:pserver:ejlp@3.219.189.99:C:/project co myproject1

Buat log file dari CVS

D:\myproject1>cvs -d:pserver:ejlp@3.219.189.99:C:/project log > logfile.txt

Buat direktori tempat output dari statcvs

D:\myproject1>mkdir cvssummary

jalankan statcvs

D:\myproject1>java -jar D:\statcvs-0.2.2\statcvs.jar -output-dir cvssummary -title "My Project 1" logfile.txt D:\myproject1StatCVS - CVS statistics generation

Jika tidak ada error kita akan kembali ke command prompt. Selasai, tinggal kita lihat hasilnya di direktori cvssummary. Click file index.html

Lihat dokumentasinya untuk command line arguments yang lebih lengkap.

Tuesday, February 22, 2005

Web service: standar baru untuk optimasi SOAP

- W3C XML Schema specification mensyaratkan binary data pada XML untuk diencode menggunakan base64 atau hexadecimal. Base64 encoding membuat data membesar 50%, sedangkan hexadecimal encoding memperbesar dua kalinya.

- SOAP menggunakan format XML sehingga binary data dapat diikutkan dengan menggunakan encoding. Tapi encoding binary data akan membuat file menjadi lebih besar sehingga tidak efektif karena memakan space, bandwith serta menambah proses encoding/decoding.

- Binary data dalam SOAP message bisa direpresentasikan dalam format byte array, dengan menggunakan tipe xsd:hexBinary atau xsd:base64Binary. Tapi Implemantasi SOAP biasanya tidak mendukung format byte array yang besar.

- Transfer binary data juga bisa dilakukan dengan SOAP with attachments (Sw/A), yang merupakan extension dari standar SOAP 1.1. Sw/A menggunakan MIME multipart/related message seperti pada attachement email, biasanya menggunakan base64 encoding.

- W3C membuat standar untuk mengoptimalisasi transmisi paket SOAP dengan standar XML-binary Optimized Packaging (XOP), SOAP Message Transmission Optimization Mechanism (MTOM), dan Resource Representation SOAP Header Block (RRSHB).

- XOP membuat encoding binary data pada dokumen XML menjadi lebih efisien. XOP bekerja pada level XML Information Set (Infoset) sehingga representasi abstrak dari XML dokumen dapat dapat diserialisasi (deserialize) dengan cara yang berbeda-beda.

- MTOM mendefinisikan bagaimana XOP dapat ditransmisikan dengan optimal menggunakan SOAP message. MTOM bisa menjadi solusi pengganti SOAP with Attachments (Sw/A) yang tidak di support oleh Microsoft sampai saat ini.

- RRSHB mendefiniskan bagaimana SOAP client dapat menggambil data dari original resource atau dari cache (local data) sehingga tidak perlu adanya transmisi lewat network.

- Karena ke-3 recomendation W3C tersebut baru dirilis 25 January 2005, jadi belum ada implementasi library untuk itu. Mungkin dari BEA, IBM atau Microsoft akan segera merilis library untuk memudahkan kita melakukan implementasi karena ketiga perusahaan tersebut yang banyak meberpartisipasi pada ke-3 recomendation tersebut.

- Ke-3 recomendation ini akan jadi next standar web service baru selain standar SOAP baru, SOAP 1.2

Monday, February 21, 2005

Java: Tutorial menggunakan testing framework dengan JUnit

JUnit: Pengalaman pertama

Hari ini saya mencoba menggunakan JUnit test, unit testing framework untuk Java. Awalnya dari extreme programming, saya tau mengapa unit test begitu penting. Jadi sudah tau JUnit sudah lama tapi tidak pernah sampai mencoba menggunakannya karena merasa tidak ada waktu dan tidak dibutuhkan, selain itu proyek-proyek yang salakuakan biasanya memiliki time frame yang ketat artinya bukan sekedar waktu yang sangat sempit bahakan bisa dibilang sebenarnya proyek tidak bisa selesai dengan jangka waktu yang ditetapkan. Jadi prosedur testing sering kali dilakukan berbarengan dengan waktu development atau tidak ada fase testing yang cukup sehingga kualitas produknya rendah dan sering terjadi kesalahan pada saat sistem/program telah masuk masa production. Saya kira ini sering terjadi di proyek IT di Indonesia, yang tingkat korupsinya masih tinggi dan pengharaan waktunya kurang.

Pengalaman pertama yang memaksa saya melakukan unit testing adalah, database development saya ngaco (tidak bisa digunakan) ketika saya sedang melakukan bug fixing. Setelah bug di-fix, tentu saja saya tidak bisa melakukan testing di mesin production maka saya melakukan simulasi (tes) dengan menggunakan JUnit dan beberapa mock object sehingga testing bisa dilakukan tanpa perlu koneksi ke database. Sekarang saya akan menjelaskan sedikit tentang bagaimana menggunakan Junit untuk unit tes, tentu saja ini hanya sebuah artikel contoh penggunaan yang tidak menyeluruh.

Pertama download Junit framework di JUnit.org, kemudian simpan jar file di CLASSPATH

Kemudian mualailah coding class untuk testing. Class untuk testing tersebut akan memiliki format seperti ini:

import junit.framework.TestCase;

public class NamaClass_Test extends TestCase {
public NamaClass_Test(String name) {
super(name);
}

public void testSesuatu() {
// assert disini
}

public void testSesuatuLagi() {
// assert disana
}

public void testSesuatuLainnya() {
// assert dimana-mana
}
}

Unit class test yang kita buat harus merupakan child dari class junit.framework.TestCase, didalam unit class test tersebut kita dapat meng-override method setUp() untuk meletakan inisialisai varibel atau proses tertentu, dan meng-override method tearDown() untuk menyimpan bagian-bagian yang harus dieksekusi setelah test dalam class tersebut selesai, misalnya menutup koneksi ke database.

Jangan gunakan constructor untuk menginisialisasikan sesuatu yang akan ditest, gunakanlah setUp(), karena jika terjadi error akan menghasilkan error message yang tidak informatif yaitu unit.framework.AssertionFailedError: Cannot instantiate test case ...

Selain itu kita dapat membuat method-method public tanpa return value (void) dengan awalan test untuk meletakan kode testing kita.
Didalam method test yang kita buat, kita melakukan assertions (kamus: to state or express positively) yaitu membandingkan hasil aktual dengan hasil yang diharapkan (expected).

assertEquals(...)
assertTrue
(...)
assertFalse(...)
assertNull(...)
assertNotNull(...)
assertSame(...)
assertNotSame(...)
fail(...)

Lihat dokumentasi untuk lebih jelasnya mengenai method-method diatas. Method assert diatas pada umumnya memiliki argumen (expected_result, actual_result) atau (Pesan_Kesalahan, expected_result, actual_result). Jika hasil expected_result sama actual_result maka JUnit akan mengganggap test sukses.
perhatikan method dengan assertion berikut ini:

public void testSesuatu() {
SomethingVO someVO = (new BusinessClass()).transferToManager(99);
assertEquals(
"SomethingVO tidak bisa ditransfer",
new SomethingVO("Something No 99"),
someVO);
}

Pada contoh diatas JUnit akan mengecek apakah result object someVO sama dengan expected object SomethingVO("Something No 99"), jika sama maka kita dapat mengatakan method transferToManager lulus tes.

Dengan menggunakan banyak method berawalan test dalam satu class, kita megumpulakan satu fungsional test dalam satu class dan kita akan dapat dengan mudah meng-execute semua method-method tersebut dengan cara membuat method main seperti ini:

public static void main(String[] args) {
TestRunner.run(NamaClass_Test.class);
}

Contoh output jika class tersebut di-execute adalah :

There were 2 failures:
1) testSesuatu(com.test.NamaClass_Test)junit.framework.AssertionFailedError: Sesuatu is NOT accepted
at com.test.CaseWorklistTest.testTransferToCollector(NamaClass_Test.java:76)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.test.NamaClass_Test.main(NamaClass_Test.java:174)
2) testSesuatuLagi(com.test.NamaClass_Testjunit.framework.AssertionFailedError: Sesuatu is already assign
at com.test.NamaClass_Test.testAssign(NamaClass_Test.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.test.NamaClass_Test.main(NamaClass_Test.java:174)

FAILURES!!!
Tests run: 3, Failures: 2, Errors: 0

Nah, kita bisa lihat ada 3 tes yang telah run, ada 2 assertion failure dan 0 error.

JUnit memberikan beberapa cara yang dapat dilakukan untuk mengeksekusi class TestCase, kita bisa membuat main method seperti diatas atau bisa menggunakan GUI tool

java -classpath D:\junit3.8.1\junit.jar junit.swingui.TestRunner NamaClass_Test

Kita dapat mengelompokan beberapa TestCase menjadi satu group/suite dengan menggunakan class TestSuite. Dengan TestSuite, kita dapat menjalankan banyak TestCase sekaligus dan bahkan menggabungkan atau menjalankan beberapa TestSuit sekaligus.

public class SuitSuiw_Test() {
public static Test suite ( ) {
TestSuite suite = new TestSuite();

// Tambahakan dua buah TestCase bernama NamaClass0_Test dan NamaClass1_Test
// dan sebuah TestSuit bernama NamaClass2_Test
suite.addTest(new NamaClass0_Test("testMoneyEquals"));
suite.addTest(new NamaClass1_Test("testSimpleAdd"));
suite.addTest(new NamaClass2_Test().suite());
}
}

Kemudian buatlah main method untuk eksekusi

public static void main (String[] args) {
junit.textui.TestRunner.run( suite() );

// Gunakan statement dibawah ini untuk hasil dengan GUI
//junit.swingui.TestRunner.run( suite() );
}

Selesai..

Sunday, February 20, 2005

Smart Value Object (SVO)

Kita biasanya menggunakan pattern Value Object atau Transfer Object, yaitu membuat object yang hanya properties untuk menyimpan nilai-nilai.
Object tersebut berguna untuk menghubungkan antar layer dalam arsitektur J2EE, misalnya antar presentation layer dengan business, atau business layer dengan data layer, interaksi client dengan server.

SVO dibuat dengan tujuan mempermudah tracking pengubahan pada bussines object (VO) dengan menggunakan byte code processing untuk pengecekan adanya perubahan pada VO tersebut.

Jika VO mengalami perubahan maka kita tinggal mengirimkan VO tersebut ke object Mediator yang berperan sebagai pemroses modifikasi data (misalnya input/update/delete ke database). Mediator juga akan berperan sebagai pendeteksi jika ada concurrent access, sehingga terhindar dari synchronization problem. Mediator adalah sebuah Interface yang implementasinya berbeda-beda sesuai dengan data layer.

Konsep SVO bisa dilihat di gambar berikut:



SDO menggunakan pengecekan secara byte code terhadap VO, sehingga VO yang kita buat seperti layaknya VO biasa, tidak ada penambahan code apapun untuk mejadi bagian dalam SVO.

Contoh code SVO :

TestVO test = new TestVO();
test.setId(new Long(0));
TestVO result = myMediator.getGraph(test);
result.setName("new");
myMediator.updateGraph(result);
result.setName("new2");
// try to do a second update without obtaining the last version first
myMediator.updateGraph(result); // will throw ConcurrencyException


Deskripsi lengkap tentang SVO bisa di lihat di websitenya. SVO menggunakan BSD license.

Thursday, February 17, 2005

Java: Penggati standar class untuk waktu/tanggal dan kalender

Beberapa base class standar Java tidak disukai oleh developer karena beberapa masalah. Seperti Java Collections Framework, kita bisa menggunakan alternatif Commons Collection sebagai replacementnya.

Katanya penggunaan java.util.Date dan java.util.Calendar dari Sun JRE juga tidak bagus karena beberapa masalah seperti lambat, masalah synchronization, sulit digunakan untuk perhitungan waktu dan lain-lain. Karena itu kadang orang membuat function sendiri dengan perhitungan yang simple untuk kalkulasi waktu/tanggal bahkan beberapa project open source membuat library sendiri sebagai replacement dari standar Date/Calendar API Java.

Informasi yang cukup bagus tentang ini, bisa dilihat di halaman CalendarDate project.

Link dibawah ini beberapa project free java library untuk keperluan tanggal/waktu dan kalender :

Saturday, February 12, 2005

JCE provider

Dua Java Cryptography Extension (JCE) provider ini free of charge dan lisensinya simpel:

Java: Oracle Collection Object

Ini pengalaman partner saya. Dia bikin oracle object seperti ini:

CREATE OR REPLACE
TYPE T_SOMETHING AS OBJECT
(
PK_SOMETHING NUMBER,
SOMETHING VARCHAR2(10)
);
/

Kemudian dia bikin collection dari object tersebut:

CREATE OR REPLACE
TYPE "T_COLL_SOMTHING" AS TABLE OF T_SOMETHING;
/

Collection object tersebut digunakan sebagai return dari sebuah oracle function

CREATE OR REPLACE FUNCTION GET_SOMETHING(a_date DATE)
RETURN T_COLL_SOMTHING
IS
...
...
...dihapus...

Yang membuat pusing adalah, di develompent server (embedded WAS di WSAD 5.1.0/JRE1.3) code java dibawah ini menghasilkan nilai hexadesimal.

CallableStatement cs = conn.prepareCall("BEGIN ? := get_something( ? ); END;");
cs.registerOutParameter(1, Types.ARRAY, "T_COLL_SOMTHING");
cs.setDate(2, currDate);
cs.execute();

Array res = cs.getArray(1);
rs = res.getResultSet();

while (rs.next()){
java.sql.Struct struct = (java.sql.Struct)rs.getObject(2);
Object[] objectArray = struct.getAttributes();
String s = (String)objectArray[1];
System.out.print(s);
}

Jika varibel string "s" dikonversi dari hexa ke kode ascii, didapatkan hasil yang diinginkan.

URL dari google ini http://forums.oracle.com/forums/thread.jsp?forum=99&thread=228159&message=640498
menyarankan untuk menambahkan nls_ charset12.zip di classpath.

Tapi tampaknya nls_ charset12.zip tidak memecahkan masalah. Di production server (WAS 5.1/JRE 1.4.2 dengan menggunakan embedded data source) menghasilkan karakater "???"

Saya coba seperti ini :
     oracle.sql.STRUCT struct = (oracle.sql.STRUCT)rs.getObject(2);
Datum[] objectArray = struct.getOracleAttributes();
String s = ((oracle.sql.CHAR)objectArray[1]).getString();
System.out.print(s);
hasilnya adalah
java.sql.SQLException : Non supported character set: oracle-character-set-178
Bagaimana ini?

Saturday, February 05, 2005

Web service: standar dan organisasi

W3C develops interoperable technologies (specifications, guidelines, software, and tools) to lead the Web to its full potential. W3C creates a final specification or set of guidelines called Recommendation.

SOAP (Simple Object Access Protocol), WSDL (Web Services Description Language), UDDI (Universal Description, Discovery and Integration), XML (EXtensible Markup Language), XML Schema

OASIS is a not-for-profit, international consortium that drives the development, convergence, and adoption of e-business standards. Final realease of their standard called OASIS Standard.

OASIS Standards are approved within an OASIS Committee, submitted for public review, implemented by at least three organizations, and finally ratified by the Consortium's membership at-large.

WSRP (OASIS Web Services for Remote Portlets), WSS (Web Services Security),UDDI Specification, WSRM (Web Services Reliable Messaging)

WS-I is an open industry organization chartered to promote Web services interoperability across platforms, operating systems and programming languages.

WS-I makes :
  • Profiles provide implementation guidelines for how related Web services specifications should be used together for best interoperability.
  • Sample Applications demonstrate Web services applications that are compliant with WS-I guidelines.
  • Testing Tools are used to determine whether the messages exchanged with a Web service conform to WS-I guidelines.
Basic Profile 1.1, Simple SOAP Binding Profile 1.0, Attachments Profile 1.0

Oracle: Hati-hati dengan data NULL

Jika kita jalankan procedure dibawah, apa yang akan kita dapatkan?

CREATE OR REPLACE PROCEDURE example AS
init NUMBER;
result NUMBER;
BEGIN
init := 25;
result := init + NULL;
dbms_output.put_line('Result = '|| result);
END;

Suatu operasi aritmetika pada varibel not null dengan varibel null, hasilnya null.

Apa yang kita dapatkan jika kita menjalankan query dibawah ini dan field column1 pada tabel my_table memiliki data NULL?

SELECT * FROM my_table WHERE column1 <> 0;

Kita tidak mendapatkan record yang column1 berisi NULL.

Karena saya bukan DBA atau database programmer, sempat juga membuat kesalahan . Jadi hati-hati dengan NULL. Baca Oracle "PL/SQL User's Guide and Reference" bagian Expressions and Comparisons, Handling Nulls:
  • comparisons involving nulls always yield NULL
  • applying the logical operator NOT to a null yields NULL
  • in conditional control statements, if the condition yields NULL, its associated sequence of statements is not executed

Oracle: Membuat synonym

Kadang kita perlu mempunyai user lain yang memiliki otoritas/role yang lain untuk mengakses suatu schema. Misalnya saja kita butuh user yang memiliki hak akses read only pada suatu schema.

Misalkan kita buat user FOO adalah user yang memiliki akses read only ke schema BAR. User A akan kerepotan dalam mengakses object di schema BAR, karena setiap dia akan mengakses object di schema BAR maka harus menuliskan BAR.NAMA_OBJECT.

Untuk memudahkannya kita bisa buat sysnonym dari table, view, procedure, function dan package object yang ada di schema BAR untuk si FOO.


set heading off;
set linesize 200;
set feedback off;

spool c:\create_synonym.sql

SELECT 'CREATE SYNONYM ' || object_name || ' FOR ' || owner ||'.'|| object_name || ';' script
FROM all_objects
WHERE owner = 'BAR'
AND object_type IN ('PROCEDURE','FUNCTION','TABLE','VIEW','PACKAGE');

spool off;

Followers