Bab V Implementasi dan Pengujian Setelah tahap perancangan dilakukan di bab sebelumnya, maka pada Bab 5 ini akan diimplementasi hasil rancangan solusi rekayasa ulang tersebut ke dalam lingkungan bahasa pemrograman dan DBMS jika terdapat penambahan store procedure yang mendukung proses yaitu Ms SQL Server 2005. Tahap implementasi ini juga meliputi proses konversi dan migrasi beberapa fungsi-fungsi yang ada pada versi web-based ke wap-based dan sms-based. Implementasi pada lingkungan ini mengikuti konvensi penamaan pada Lampiran Q yang sudah ditetapkan dalam organisasi. Masalah penamaan pada lampiran tersebut terdiri atas penamaan field/properti, variabel kontrol, variabel objek kelas, store procedure dan lokasi bagian web. Penamaan yang baik akan membuat suatu program dapat mudah dilacak jika pada suatu saat akan melakukan perubahan atau mengatasi masalah yang terjadi pada saat program telah berjalan. Adapun tahapan-tahapan yang dilakukan dalam proses implementasi solusi rekayasa ulang, yaitu: 1. Implementasi solusi refactoring terhadap suatu bad smells yang telah ditemukan ke bahasa pemrograman. 2. Migrasi sebagian fungsi-fungsi pada versi web-based ke wap-based dan sms-based. Pengujian refactoring dan migrasi; pada tahap ini dilakukan pengujian terhadap implementasi kode dengan skenario-skenario tertentu. Pengujian ini bertujuan untuk melihat apakah refactoring dan migrasi yang telah dilakukan berjalan dengan sukses sesuai dengan yang diinginkan.
V.1
Implementasi Solusi Refactoring
Diantara bad smells yang telah ditemukan pada Bab III, maka penanganan smells dilakukan secara berurut mulai dari Dead Code. Untuk mengatasi Dead Code, biasa hanya menghapus kode itu saja atau memberikan comment pada kode itu jika pada sewaktu-waktu ternyata tidak diketahui bahwa kode tersebut dibutuhkan, padahal dengan bantuan tools terdeteksi bahwa bagian kode itu merupakan Dead Code. 70
Bad smells yang terdapat pada program terdiri dari code smells dan class smells. Code smells pada umumnya terlihat pada suatu program yang bersifat prosedural dengan melihat pola-pola tertentu berdasarkan smells yang telah dipelajari pada [2]. Class smells dapat muncul dan menyebabkan organisasi kelas tersebut menjadi tidak baik, sehingga kode yang dihasilkan akan menjadi tidak efektif. V.1.1 Code Smells V.1.1.1 Masalah penamaan tak konsisten Nama yang tidak konsisten adalah nama field. Nama yang memiliki semantik yang sama harus diseragamkan. Dalam hal ini terdiri atas dua kasus, yaitu: 1. BranchView: a. SalesPersonName diganti Adviser b. Office diganti Branch 2. AdviserView: a. ServiceCategory diganti CurrentClientCategory b. NewServiceCategory diganti NewClientCategory
Langkah pengerjaan dimulai dari kelas BranchView point a, kemudian point b. Setelah itu masuk ke kelas Adviser mulai dari point a dan b. Untuk masing-masing point, langkah-langkah terdiri dari: 1. Pada bagian private field (bagian atas tubuh kelas), klik kanan pada nama variabel, kemudian pilih “Rename” (Gambar V.1). 2. Setelah muncul Dialog Box, maka ganti nama private field itu dengan nama baru (Gambar V.2). 3. Pada bagian properti (bagian bawah tubuh kelas), klik kanan pada nama properti, kemudian pilih “Rename” (Gambar V.3). 4. Setelah muncul Dialog Box, maka ganti nama properti itu dengan nama baru (Gambar V.4).
71
Gambar V.1 Klik kanan-Rename pada private field
Gambar V.2 Dialog box untuk mengganti nama private field
Gambar V.3 Klik kanan-Rename pada properti
72
Gambar V.4 Dialog Box untuk mengganti nama properti
V.1.1.2 Masalah Duplikasi Berdasarkan bagian IV.1.2, nomor 1 dan 2 tidak menggunakan polymorphism, sedangkan nomor 3 dan 4 menggunakan polymorphism yang mengekstrak kelas baru. Langkah-langkah umum untuk mengimplementasikannya: 1. Tentukan bagian dari proyek web yang menggunakan method itu dengan menggunakan tools bernama Reflector. Aturan penamaan lokasi web telah dibahas pada Lampiran Q. 2. Pada tiap bagian lokasi web, ganti nama lama dari method itu dengan nama baru yang telah diusulkan pada Lampiran N.
Untuk nomor 3 pada IV.1.2, kelas diagram hasil implementasi yang terbentuk menjadi seperti Gambar V.5.
Gambar V.5 Kelas diagram hasil implementasi dari DateComment
73
Sedangkan rincian superclass yang terbentuk menjadi seperti Gambar V.6.
Gambar V.6 Rincian Kelas pada DateComment
Pada tiap subclass dari DateComment dapat diisi method konstruktor seperti pada Tabel V.1. Tabel V.1 Isi method konstruktor dari SRDateComment dan NRDateComment
SRDateComment ubahKomentar("SR meeting completed on ") ubahNamaKontrol("e_calSRDate")
NRDateComment ubahKomentar("SR meeting moved to ") ubahNamaKontrol("e_calNRDate")
Untuk nomor 4 pada IV.1.2, kelas diagram hasil implementasi yang terbentuk menjadi seperti Gambar V.7.
Gambar V.7 Kelas diagram hasil implementasi dari AgingIndicator
Rincian dari superclass yang terbentuk menjadi seperti Gambar V.8.
74
Gambar V.8 Rincian kelas pada AgingIndicator
Source code yang lengkap untuk solusi polymorphism (nomor 3 dan 4 pada IV.1.2) dapat dilihat pada Lampiran O. Kode ini melengkapi dari Lampiran N mengenai solusi duplikasi yang telah ditulis sebagian.
V.1.1.3 Masalah Feature Envy Pada kasus GetChangeCategory_for_sent_to_GM dan InsertToChangeCategory, langkah pertama yang dilakukan yaitu dengan cut keseluruhan isi method dari kelas AdviserView, lalu paste ke ClientCategoryChange. Untuk mengetahui bagian program mana saja yang menggunakannya, maka dapat menggunakan Reflector. Bagian program yang terdeteksi menggunakan method itu harus mengganti bagian kode tertentu yang mengandung inisialisasi dari suatu kelas agar mengganti dengan kelas yang benar. Jika masih terdapat error yang 75
menunjukkan field tersebut belum dideklarasikan di kelas itu, maka tambahkan beberapa field yang dibutuhkan pada kelas itu.
Jika method itu adalah method umum seperti pada kasus ComparingDate dan CustomDate, maka langkah implementasinya yaitu cukup menggunakan cut-paste biasa dari file AdviserView.vb ke ModulUmum.vb.
Pada kasus method GetLatestNRD dan GetLatestDLS, implementasinya dengan langsung menggunakan cut-paste dari ClientList.aspx ke ModulUmum.vb, kemudian ConnSupport dari kedua method tersebut diganti PConn karena variabel PConn sudah dideskripsikan sebagai variabel dari objek koneksi.
Pada kasusCentralProcessChangeCategory dan ChangeCategory, langkah implementasinya mirip dengan kasus GetChangeCategory_for_sent_to_GM dan InsertToChangeCategory. Seperti pada bagian IV.1.3 paragraf kelima, hasil akhir akan terdapat method ChangeCategory dengan satu parameter.
V.1.1.4 Masalah Divergent Change Dropdownlist yang sering dipakai itu adalah untuk branch dan adviser. Kombinasi dropdownlist dengan textbox yang membentuk perioda juga banyak diulang-ulang di banyak tempat. Langkahlangkah implementasinya: 1. Buat UserControl pertama yang hanya terdiri dari satu dropdownlist yang menampilkan daftar nama-nama branch. 2. Buat UserControl kedua yang terdiri dari dua kontrol, yaitu: a. UserControl pertama yang menampilkan nama-nama branch. b. Dropdownlist yang menampilkan nama-nama adviser jika nama branch berubah. 3. Buat UserControl ketiga yang terdiri dari dropdownlist bulan dan textbox tahun. 4. Buat UserControl keempat yang terdiri dari tiga kontrol, yaitu: a. UserControl pertama yang menampilkan nama-nama branch. 76
b. Dropdownlist yang menampilkan nama-nama adviser jika nama branch berubah. c. UserControl ketiga yang terdiri dari dropdownlist bulan dan textbox tahun 5. Lekatkan UserControl yang memiliki dropdownlist branch saja pada halaman di bawah ini: a. Central_Summary_Sub b. Central_ZeroServicingPeriod 6. Lekatkan UserControl yang memiliki dropdownlist branch dan adviser pada halaman di bawah ini: a. Central_ClientListPlusNRD b. Central_ R_ClientWOSR 7. Lekatkan UserControl yang memiliki perioda, branch dan adviser pada halaman di bawah ini: a. Branch_SF002 b. Central_R_Reschedule c. Central_R_SF001 d. Central_R_SF002 8. Lekatkan UserControl yang hanya memiliki perioda saja pada halaman di bawah ini: a. Central_R_SF003 b. Central_R_SRGeneralReport 9. Pada nomor 4, 5 dan 6, sesuaikan penanganan event-nya yang mengambil nilai dari objek UserControl itu.
V.1.2 Class Smells V.1.2.1 Duplikasi field Langkah-langkah dalam mengimplementasikan: 1. Gunakan cut-paste untuk memindah method (yang disebutkan pada IV.2.1) dari kelas lama (pada Lampiran B) ke kelas yang baru yang telah diusulkan, kelas entitas awal yaitu Client dan Schedule. 2. Jika terdapat daftar error bahwa field tersebut tidak dikenal, untuk sementara ciptakan properti dan private field di kelas entitas awal itu. 77
3. Jika terdapat daftar error bahwa “X is not a member of ‘ServicingX.dev.Y’” dimana X adalah nama method dan Y adalah nama kelas, maka langsung menuju lokasi file yang mengandung error itu untuk mengganti inisialisasi kelas yang awalnya bukan kelas Y menjadi kelas Y. Dari tahap nomor 1 sampai nomor 3, maka akan terbentuk kelas diagram sementara seperti pada Lampiran H. Tahap berikutnya mengelompokkan field-field ke kelas dan menambah tiga kelas tambahan lagi seperti Adviser, ActionTakenRequired dan SystemUser. Langkah berikutnya: 4. Buat tiga kelas baru (Adviser, ActionTakenRequiren dan System User) sesuai rancangan pada Gambar IV.4, tipe data dasar untuk field harus sesuai dengan tabel Q.1 pada Lampiran Q. 5. Buat private field bertipe kelas sesuai dengan rancangan pada Gambar IV.4, lengkap dengan propertinya. Penamaan untuk kepemilikan field bertipe kelas pada kelas dalam rancangan kelas diagram itu (pada Gambar IV.4) telah mengikuti perjanjian pada Lampiran Q. 6. Pada method yang keluarannya berupa DataTable, jika field-field merupakan input (sintaks untuk memasukkan parameter ke store procedure), maka field yang bukan milik kelas induk itu ditambahkan <private field bertipe kelas> di depan private field itu dan tanda _(underscore) dihilangkan yang menandakan private field. Misalnya field input bernama “_Branch”, maka diubah menjadi “_ClientAdviser.Branch”. Sintaks dalam kotak dibawah ini adalah contoh input:
Comm.Parameters.Add(New SqlParameter("@branch", SqlDbType.Char, 60, ParameterDirection.Input, False, 0, 0, "", DataRowVersion.Proposed, _ClientAdviser.Branch))
7. Jika field-field merupakan output, maka dideklarasikan konstruktor untuk menciptakan objek dari kelas itu sebelum properti dari private field bertipe kelas itu di-assign suatu nilai. Field yang bukan milik kelas induk itu ditambahkan <private field bertipe kelas> di depan private field itu dan tanda _(underscore) dihilangkan yang menandakan private field. Contoh dari sintaks tersebut:
_ClientSchedule = New EntityClass.Schedule _ClientSchedule.SRDate = New SqlString(CType(ToReturn.Rows(0)("srdate"), String))
78
8. Dengan menggunakan Reflector, tentukan bagian-bagian web yang memanggil method itu. 9. Pada tiap-tiap bagian web, jika terdapat satu variabel objek kelas (kelas induk) dan ternyata objek kelas itu memiliki properti bertipe kelas (kelas anak), maka buat variabel untuk objek kelas lain yang tetap mengikuti peraturan pada Lampiran Q, variabel objek kelas yang lama dapat diganti mengganti nama lain pula sesuai peraturan pada Lampiran Q agar mudah dilacak. 10. Assign nilai untuk kelas anak terlebih dahulu, kemudian properti dari kelas induk yang bertipe kelas di-assign dengan kelas anak. Contoh sintaks:
Dim Func_Client As New EntityClass.Client Dim func_adviser As New EntityClass.Adviser Dim func_sys As New EntityClass.SystemUser func_sys.MonthYear = New SqlString(Trim(txtYear.Text) + Trim(ddlMonth.SelectedItem.Value)) func_adviser.AdviserName = New SqlString(Trim(ddlAdviser.SelectedItem.Value)) func_adviser.Branch = New SqlString(Trim(ddlBranch.SelectedItem.Value)) 'datatable bisa ambil dari cache Func_Client.ClientAdviser = func_adviser Func_Client.ClientSystem = func_sys
11. Setelah semua bagian web menyesuaikan pemanggilan method itu, maka field-field yang tidak dibutuhkan pada kelas itu dapat dihapus.
V.1.2.2 Data Class Properti yang berisi method setter dan getter biasa diletakkan di bagian bawah dari tubuh kelas, untuk properti yang memerlukan setter dan getter, maka penulisannya adalah sebagai berikut: Public Property NamaProperty() As DataType Get Return _NamaField ‘1. Baris Getter End Get Set(ByVal value as DataType) _NamaField=value ‘2. Baris Setter End Set End Property
79
Jika ada kelas bernama X dengan properti bernama a. Maka untuk menyetel nilai tersebut dilakukan dengan:
X.a = nilai, sedangkan untuk mendapatkan nilai dapat secara langsung
mencetak isi dari X.a. Field yang memerlukan getter saja, maka format penulisannya akan menjadi: Public ReadOnly Property NamaProperty() As DataType Get Return _NamaField ‘1. Baris Getter End Get End Property
Sedangkan yang memerlukan setter saja, format penulisannya menjadi: Public WriteOnly Property NamaProperty() As DataType Set(ByVal value as DataType) _NamaField=value ‘2. Baris Setter End Set End Property
Untuk private field yang tidak membutuhkan method setter dan getter, maka tidak perlu mendeklarasikan properti di bagian bawah kelas. Jenis constraint yang terdapat pada Lampiran J seperti yang disebutkan pada bagian IV.2.2 ada 11, 3 dari 11 constraint menggunakan Regular Expression. Untuk constraint jenis Periode (yyyymm), maka isi method setter-nya menjadi: If Len(value.ToString) = 6 Then 'YYYYMM _namafield = value Else If Now.Month < 10 Then _ namafield = Now.Year.ToString & "0" & Now.Month.ToString Else _ namafield = Now.Year.ToString & Now.Month.ToString End If End If
Untuk constraint jenis karakter bebas, maka tidak perlu ada penyaringan. Maka isi method setter menjadi “_namafield=value”. Untuk jenis Money juga dapat melakukan assignment langsung tanpa adanya penyaringan karena jika isi yang invalid akan tertangkap sewaktu run time. Untuk constraint jenis Bit, maka isi method setter-nya menjadi: 80
If value = 0 Or value = 1 Then _ namafield = value Else _ namafield = 0 End If
Untuk jenis bilangan bulat positif, isi method setter-nya: If value >= 0 Then _ namafield = value Else _ namafield = 0 End If Untuk jenis tanggal, isi method setter-nya If IsDate(value.ToString) Then _ namafield = value Else _ namafield = Now().ToString("dd/mm/yyyy") End If
Untuk jenis bilangan bulat terbatas 0-12, maka isi method setter-nya If value >= 0 And value <= 12 Then _ namafield = value Else _ namafield = 12 End If
Untuk jenis Char/karakter, maka isi method setter-nya If Len(value.ToString) = 1 Then _ namafield = value Else _ namafield = "" End If
Tiga constraint lainnya menggunakan Regular Expression, yaitu: 1. Nama orang, pola regex-nya: ^[\',.a-zA-Z ""_-]*$ 2. Nama branch, pola regex-nya: ^[a-zA-Z ]*$ 3. Alfanumerik, pola regex-nya: ^[0-9a-zA-Z ]*$
81
Tambahkan fungsi ini pada ModulUmum.vb agar dapat diakses dari semua bagian web agar dapat menggunakan fungsi Regular Expression. Function MatchRegex(ByVal str As String, ByVal regx As String) As Boolean Dim exp As New System.Text.RegularExpressions.Regex(regx) If exp.IsMatch(str) Then Return True Else : Return False End If End Function
Kemudian pada method setter-nya, masing-masing memiliki kode: If MatchRegex(value.toString(),regex) Then _namafield=value Else _namafield=”” End If
Nilai variabel “regex” diatas diganti dengan pola Regular Expression yang sesuai untuk tiap constraint. Untuk semua field pada tiap-tiap kelas dapat menyesuaikan gabungan antara keberadaan method setter/getter dan batasan nilai yang diperbolehkan (salah satu dari 11 constraint) sesuai dengan tabel yang ada pada Lampiran J.
V.2
Implementasi Migrasi Ke Perangkat Nirkabel
V.2.1 Migrasi ke WAP WAP memiliki keterbatasan dibandingkan dengan web. Untuk membuat halaman WAP harus menggunakan Ms Visual Studio 2003 (versi yang lebih lama) karena pada versi 2005 tidak disediakan untuk pembuatan halaman WAP. Kontrol untuk halaman WAP dan web akan berbeda, tetapi antara kontrol tersebut dapat memiliki ekivalensi walaupun cara pemanggilan method pada kontrol ada perbedaan. Untuk ekivalensi kontrol, dapat dilihat pada Tabel V.2. Tabel V.2 Ekivalensi kontrol antara Web dengan WAP
Nama kontrol untuk web Dropdownlist Button Datagrid/GridView
Nama kontrol untuk WAP Selectionlist Command ObjectList 82
Tabel V.2 Ekivalensi kontrol antara Web dengan WAP (lanjutan)
Nama kontrol untuk web ListItem ReportViewer
Nama kontrol untuk WAP System.Web.UI.MobileControls.MobileListItem ObjectList
ReportViewer untuk menampilkan report pada Crystal Report tidak didukung oleh halaman WAP, maka sebagai penggantinya dapat menggunakan ObjectList. Antara ObjectList dan Datagrid/GridView dapat memiliki nama method yang sama, yaitu untuk memberikan nilai properti “DataSource” dari objek DataTable, kemudian melakukan DataBind. Kemudian perintah lainnya yang ekivalen dengan berbasis web dan sering digunakan dapat dilihat pada Tabel V.3 Tabel V.3 Ekivalensi perintah antara Web dengan WAP
Perintah pada web
.SelectedItem.V alue Response.Redirect(“…”)
Perintah pada WAP <Selectionlist>.Selection.Value
Dim CstItem As New ListItem
Dim CstItem as New System.Web.UI.MobileControls.MobileLis tItem
Fungsi Mengambil nilai dari list Menuju ke suatu halaman tertentu Mendeklarasik an CstItem sebagai unit item dari sebuah list
RedirectToMobilePage(“...”)
Setelah mengetahui ekivalensi dari kontrol dan baris kode tertentu, maka langkah-langkah untuk mengimplementasikannya: 1. Menyalin sebagian file-file yang dari CustomClass. Tidak semua kelas-kelas dipakai, yang
tidak
digunakan
ClientDataHistorys.
yaitu:
Feeding,
Bagian-bagian
kode
ClientCategoryChange, pada
kelas
Logger
yang
dan
terdapat
“Logger.LogException(ex)” diberi comment atau tidak perlu dieksekusi. Library yang diimpor pada tiap kelas sama kecuali ServicingX_Dev.ServicingETracer. 2. Buat disain GUI seperti pada Lampiran L dan beberapa bagian kode memperhatikan ekivalensi pada Tabel V.2 dan Tabel V.3 agar mengganti dari versi web ke WAP, 83
3. UserControl pada WAP tidak didukung, agar suatu kode tidak diulang di banyak tempat (Divergent Change), maka dibuatlah tiga method baru pada ModulUmum.vb 1.Method BranchLoader: untuk memuat daftar nama-nama branch Sub BranchLoader(ByVal SlcLst As System.Web.UI.MobileControls.SelectionList) SlcLst.Items.Clear() Dim CstItem As New System.Web.UI.MobileControls.MobileListItem Dim Func As New EntityClass.SystemUser CstItem.Text = "" CstItem.Value = "%" SlcLst.Items.Add(CstItem) With Func Dim tmpRow As DataRow For Each tmpRow In .ListOfBranch.Rows Dim DbItem As New System.Web.UI.MobileControls.MobileListItem DbItem.Text = Trim(tmpRow("office")) DbItem.Value = Trim(tmpRow("office")) SlcLst.Items.Add(DbItem) Next End With
End Sub
2.Method AdviserFromBranch: untuk memuat daftar nama-nama adviser dari branch terpilih Sub AdviserFromBranch(ByVal Brc As String, ByVal SlcLst As System.Web.UI.MobileControls.SelectionList) SlcLst.Items.Clear() Dim CstItem As New System.Web.UI.MobileControls.MobileListItem CstItem.Text = "" CstItem.Value = "%" SlcLst.Items.Add(CstItem) Dim Func As New EntityClass.Adviser With Func Dim dtTable As New DataTable Dim dxView As DataRow .Branch = New SqlString(Brc) dtTable = .GetDistinctAdviserByBranch For Each dxView In dtTable.Rows Dim DbList As New System.Web.UI.MobileControls.MobileListItem DbList.Text = dxView.Item("salespersonname") DbList.Value = dxView.Item("salespersonname") SlcLst.Items.Add(DbList) Next End With End Sub
3.Method DummyAdviserFiller: untuk menampilkan data dummy pada dropdownlist dari adviser. 84
Private Sub DummyAdviserFiller(ByVal SlcLst As System.Web.UI.MobileControls.SelectionList) Dim CstItem As New System.Web.UI.MobileControls.MobileListItem CstItem.Text = "Not populated yet" CstItem.Value = "%" SlcLst.Items.Add(CstItem) End Sub
Kemudian, untuk memanggil dari beberapa halaman WAP: Pada saat event Page_Load, “BranchFiller()” diganti dengan “BranchLoader(ddlBranch)”, kemudian untuk event hyperlink “Refresh Adviser” diklik, method “AdviserFiller()” diganti dengan
“AdviserFromBranch(ddlBranch.
Selection.Value,ddlAdviser)”
dan
method
“DummyAdviserFiller” menjadi “DummyAdviserFiller(ddlAdviser)”. 4. Bagian kode yang mengimpor kelas-kelas untuk Crystal Report tidak dibutuhkan, maka kode dibawah ini diberi tanda comment agar tidak dieksekusi: Imports CrystalDecisions.CrystalReports.Engine Imports CrystalDecisions.Shared.
5. Bagian kode yang menggunakan fungsi-fungsi Crystal Report diberi comment. Sebagai gantinya, kode-kode tersebut diganti dengan kode-kode yang melakukan assignment terhadap properti DataSource pada ObjectList dengan variabel objek DataTable, kemudian melakukan DataBind terhadap ObjectList itu.Contoh potongan kodenya seperti dibawah ini: ObjectList1.DataSource = tmpTable ObjectList1.DataSource.DataBind
6. Karena keterbatasan dari ObjectList dibandingkan dengan Crystal Report dalam melakukan pengelompokkan/agregasi terhadap data dan tidak dapat mengganti label kolom data, maka harus dibuat view dan store procedure baru pada DBMS (SQL Server 2005) secara manual agar mengeluarkan output dalam bentuk tabel, sama pada versi yang berbasis web. Nama store procedure yang baru ini menggunakan inisial “Mob” yang menandakan bahwa store procedure ini dibuat khusus untuk halaman WAP. Rincian store procedure dan view yang dibuat dapat dilihat pada Lampiran P.
85
7. Untuk mengakomodasi perubahan ini, ada private field yang perlu ditambah. Pada kelas Schedule, yaitu: _SRGenc1, _SRGenc2, _SRGenc3, _SRGenc4, _SRGenc5, _SRGenc6, _SRGenc7, _COS, _handedin yang bertipe SqlInt16. 8. Kelas yang mengakses store procedure itu harus mengganti nama store procedure yang dipanggil dengan store procedure yang baru khusus untuk halaman WAP. V.2.2 Migrasi Ke SMS Aplikasi SMS Server diambil langsung dari suatu source code yang tersedia gratis dari alamat: http://twit88.com/blog/2007/09/23/how-to-receive-sms-using-net-sms-library/ Pada proyek sederhana yang terdapat pada source code itu, terdapat event handling ketika sms diterima yang isinya adalah sebagai berikut: Private Sub oGsmModem_NewMessageReceived(ByVal e As ATSMS.NewMessageReceivedEventArgs) Handles oGsmModem.NewMessageReceived txtMsg.Text = "Message from " & e.MSISDN & ". Message - " & e.TextMessage & ControlChars.CrLf End Sub
e.MSISDN adalah nomor ponsel yang mengirimkan sms dan e.TextMessage adalah pesan sms yang diterima. Isi method diatas akan menampilkan pengirim sms dan isi pesannya pada suatu textbox. Berikut ini adalah beberapa baris program yang dapat langsung digunakan untuk mengirimkan sms: If StringUtils.IsUnicode(pesansms) Then msgNo = oGsmModem.SendSMS(pengirim, pesansms, Common.EnumEncoding.Unicode_16Bit) Else msgNo = oGsmModem.SendSMS(pengirim, pesansms, Common.EnumEncoding.GSM_Default_7Bit) End If
Sebelum mengoperasikan aplikasi SMS secara langsung, maka pertama kali dibuat sebuah form pada Gambar V.9. Form tersebut terdiri atas tiga kontrol, yaitu: dua textbox (singleline dan multiline) dan sebuah tombol. Textbox yang singleline untuk menuliskan perintah sms, kemudian sebuah tombol jika diklik maka akan memproses pesan sms yang dikirimkan dan hasilnya akan muncul pada textbox yang multiline. Untuk menyimpan konfigurasi mengenai Connection String, maka perlu untuk dibuatkan app.config pada proyek itu. 86
Pada event tombol “Proses” diklik, maka method baru yang akan dipanggil yaitu ProsesSMSTerima(isisms:String). Method ini akan melakukan parsing terhadap perintah yang ada pada singleline textbox. Di dalam method ProsesSMSTerima, flowchart yang telah dirancang pada Lampiran K diimplementasikan. Akhir dari method itu mengukur panjang pesan sms balasan. Jika lebih dari 160 karakter maka akan dipecah dan dikelompokkan ke Collection yang pada akhirnya akan dikirimkan.
Gambar V.9 Form simulasi SMS
Setelah pengujian yang dilakukan pada form pada Gambar V.9 berhasil, maka dapat langsung mulai untuk mengoperasikan aplikasi SMS itu. Yang dilakukan adalah modifikasi pada form utama bernama MainForm.vb dengan langkah-langkah: 1. Salin method ProsesSMSTerima, tambah satu parameter bernama “byval pengirim as String”, ganti nama method itu menjadi processReceivedSMS. 2. Tambahkan satu baris pada event “NewMessageReceived” menjadi Private Sub oGsmModem_NewMessageReceived(ByVal e As ATSMS.NewMessageReceivedEventArgs) Handles oGsmModem.NewMessageReceived txtMsg.Text = "Message from " & e.MSISDN & ". Message - " & e.TextMessage & ControlChars.CrLf processReceivedSMS(e.TextMessage,e.MSISDN) End Sub
3. Pada bagian method processReceivedSMS, tambahkan potongan kode ini di akhir pjgstring = Len(pesanbalik)
87
Dim msgNo As String If pjgstring > 160 Then kolSMS = StringUtils.SplitMoreThan160Char(pesanbalik) sendSMSCollection(kolSMS, pengirim) Else 'langsung mengirimkan tanpa pecahan sms If StringUtils.IsUnicode(pesanbalik) Then msgNo = oGsmModem.SendSMS(pengirim, pesanbalik, Common.EnumEncoding.Unicode_16Bit) Else msgNo = oGsmModem.SendSMS(pengirim, pesanbalik, Common.EnumEncoding.GSM_Default_7Bit) End If End If
Source code lengkap hasil modifikasi dapat di-download pada: http://us.f13.yahoofs.com/bc/492abb7e_681d/bc/My+Documents/phonesmsrecv_src.rar?bfzmAP JBVi3ihp9P V.3 Pengujian Refactoring Setelah semua pekerjaan refactoring telah dilakukan, langkah selanjutnya adalah menguji fungsionalitas apakah output yang dihasilkan masih sama seperti pada saat sebelum di-refactor. Sudut pandang pengguna dalam pengujian dimulai dari tingkat Adviser, kemudian naik ke tingkat Branch dan kemudian Central. Fungsi yang tidak akan diujikan yaitu fungsi Feeding karena dianggap telah berjalan dan smells yang ada hanyalah kode mati saja. 1. Tingkat Adviser a. Pengujian Schedule Editor b. Pengujian Permintaan Decline SR c. Pengujian Permintaan Upgrade Client Category d. Pengujian Client List e. Pengujian Schedule Aging 2. Tingkat Branch a. Pengujian Report SF002 b. Pengujian Adviser List 3. Tingkat Central a. Pengujian Pemrosesan Permintaan Upgrade Client Category b. Pengujian Pemrosesan Permintaan Decline SR 88
c. Pengujian Edit Data Client d. Pengujian Report: i. SF001 ii. SF002 iii. SF003 iv. Reschedule v. Client List Plus NRD vi. Client Without SR vii. SR General Report (tidak perlu disimulasikan) viii. List Of Execution Only (tidak perlu disimulasikan) Skenario lengkap tentang pengujian ini dapat dilihat pada Lampiran R. Khusus 3.d bagian vii dan viii tidak akan dibahas pada skenario ini karena memiliki pengaruh yang sangat kecil terhadap perubahan yang terjadi pada skenario-skenario sebelumnya. V.4 Pengujian Migrasi V.4.1 Pengujian Berbasis WAP Setelah pengujian berbasis web berhasil dilakukan, maka langkah selanjutnya untuk menguji halaman yang berbasis WAP. Pengujian ini membandingkan hasil yang diperoleh dari halaman yang berbasis web. Point pada bagian V.3 tidak semuanya ada dalam berbasis WAP, yang akan dimasukkan ke dalam pengujian yaitu 1.d, 1.e, 2.a, 2.b dan 3.b. Skenario dan hasilnya dari pengujian ini dapat dilihat pada Lampiran S. V.4.2 Pengujian Berbasis SMS Pengujian ini berfungsi untuk menguji perintah sms yang telah dibangun apakah sms server yang dibangun itu bekerja sesuai yang diinginkan, pengujian tidak hanya jalur yang benar tetapi juga jalur yang tidak benar. Pada Lampiran G telah dikenal beberapa perintah sms.
Kasus umum untuk pengujian berbasis sms: 1. Pengujian dengan sintaks yang tidak dikenali 2. Pengujian dengan sintaks yang dikenali: a. Jumlah parameter kurang 89
b. Parameter berikut adalah sintaks yang tidak dikenali c. Username dan password salah d. Jumlah parameter cukup dan sintaks valid i. Hak akses tidak sesuai ii. Hak akses sesuai 1. Data ada 2. Data tidak ada Skenario dari pengujian ini beserta hasil pengujiannya dapat dilihat pada Lampiran T. V.5
Evaluasi Pengujian
V.5.1 Hasil refactoring dari berbasis web Hasil refactoring pada aplikasi berbasis web ini tetap mempertahankan behavior walaupun pada proses pengujian dapat mengandung bugs pada kode program yang umumnya disebabkan oleh kode yang belum lengkap, salah penempatan kode atau penggunaan tipe data yang kurang sesuai. Pengujian ini dapat membuktikan bahwa proses refactoring telah berhasil.
V.5.2 Hasil migrasi ke WAP Perbandingan data-data yang diuji dengan berbasis WAP dengan berbasis web adalah sama walaupun cara penyajian dan bentuk interaksinya sedikit berbeda. Nilai data yang sama ini dapat menunjukkan bahwa proses migrasi ke WAP berhasil.
V.5.3 Hasil migrasi ke SMS Pengguna level Central dapat memiliki akses yang tinggi, hasil yang tidak menghasilkan data akan muncul jika: 1. Klien atau adviser tidak terdaftar. 2. Klien terdaftar tetapi tidak memiliki datelastseen karena belum pernah ada jadwal yang telah dipenuhi oleh adviser. 3. Adviser terdaftar tetapi pada periode tertentu belum dibuatkan jadwal terhadap klien. Pengguna level Branch dapat memiliki akses ke branch tertentu yang diberi otoritas. Branch yang tidak diberi otoritas maka akan ditolak pengaksesannya. Misalnya ada pengguna branch 90
hanya diberi otoritas untuk mengakses branch Indonesia, maka tidak dapat mengetahui informasi pada branch selain Indonesia termasuk informasi adviser beserta kliennya. Hasil untuk pengguna branch tidak akan menghasilkan data jika: 1. Klien terdaftar tetapi tidak memiliki datelastseen karena belum pernah ada jadwal yang telah dipenuhi oleh adviser. 2. Adviser terdaftar tetapi pada periode tertentu belum dibuatkan jadwal terhadap klien. Pengguna level Adviser hanya dapat mengetahui informasi klien-klien yang merupakan miliknya dan tidak dapat mengetahui informasi klien dari adviser lain. Hasil untuk pengguna adviser tidak akan menghasilkan data jika Klien terdaftar tetapi tidak memiliki datelastseen karena belum pernah ada jadwal yang telah dipenuhi oleh adviser. Cara pengguna dalam berinteraksi dengan aplikasi sms berbeda dengan yang berbasis web dan WAP, tetapi data yang diminta dapat menunjukkan hasil yang sama. Ini menunjukkan bahwa proses migrasi berhasil. V.5.4 Kendala dan cara mengatasinya Pada proses pengujian ini dapat ditemukan suatu kendala yang bersifat teknis, yaitu masalah pada basis data. Pesan error yang umum terjadi pada basis data adalah “timeout expired”. Untuk mengatasi hal ini, maka server basis data harus di-restart. Untuk pengujian berbasis WAP, kendala yang ditemukan dapat sama seperti berbasis web, yaitu “timeout expired”. Masalah lainnya adalah kualitas jaringan GPRS atau wifi (jika perangkat nirkabel dilengkapi dengan fasilitas wifi) yang kurang baik pada suatu daerah pada saat mengakses aplikasi itu. Untuk pengujian berbasis sms, kendala yang ditemukan pada umumnya: 1. Masalah pada perangkat: terjadi kerusakan pada perangkat, perintah-perintah umum pada perangkat itu tidak dikenali, waktu respon pada perangkat itu lambat, port untuk mengkoneksikan perangkat nirkabel ke komputer ada masalah, dan sebagainya. 2. Masalah pada operator GSM: kualitas sinyal lemah, lalu lintas jaringan yang padat. Sebelum melakukan pengujian berbasis sms, maka harus dipastikan bahwa port-port yang menghubungkan perangkat nirkabel ke komputer masih dalam keadaan baik, perintah-perintah
91
umum masih dapat dikenali oleh perangkat itu dengan konfigurasi koneksi yang sudah dikenal baik. Jika kondisi perangkat dianggap sudah baik, maka harus diperiksa sim card di dalam operator GSM itu apakah masih dalam masa aktif, pulsa masih cukup, atau lalu lintas jaringan pada saat itu sedang baik atau tidak.
92