BAB 15 Design Pattern - JENI Web Programming Bab 15 Design Pattern

  1 5 .1 Pe n ge n a la n pa da D e sign Pa t t e r n 1 5 .1 .1 Apa k a h D e sign pa t t e r n ?

  Secara singkat , Design pat t ern adalah sebuah solusi unt uk m engulang m asalah Design. Solusi ini t elah dikem bangkan, dikom pile, dan disaring oleh program m er yang sebelum nya t elah m enghadapi m asalah ini. Sebuah Design pat t ern adalah salah sat u j enis pet unj uk yang m enggunakan t ipe " Jika Anda m em iliki m asalah ini, m aka lakukan ini." Hal t ersebut serupa dengan sebuah algor it m a : sebagai cont oh, j ika Anda ingin m elakukan sebuah operasi pencarian pada sebuah daft ar, Anda t idak perlu m enyelesaikan dengan solusi Anda sendiri; t erdapat beberapa algorit m a yang m enyediakan fungsi sort ing ini sepert i pencarian biner. Perbedaan ant ara sebuah Design pat t ern dan sebuah algor it m a adalah bahwa algorit m a fokus pada im plem ent asi solusi : sebuah algorit m a biasanya m endaft ar dari at as ke bawah m enuj u ke t ahap akhir dari act ion- act ion yang t erurut dim ana yang dibut uhkan unt uk m enghasilkan sebuah solusi. Sebuah pat t ern m em usat kan unt uk m enghasilkan beberapa Design : Hal t ersebut m em berit ahu kepada pengem bang apa yang harus diperbuat sebagai law an dari bagaim ana cara m elakukannya.

  Mungkin t idak t erlihat langsung hasilnya, t et api Kit a t elah siap m enggunakan beberapa Design pat t ern dalam pem bahasan Kit a sebelum nya. Sat u, Kit a t elah belaj ar secara det ail pat t ern dari Model- View- Cont roller : diberikan sebuah m asalah int eraksi gabungan yang begit u kom plek s ant ara present asi dan layer business, Hal it u m enent ukan pem isahan kode m enj adi t iga layer t erpisah sepert i int eraksi- int eraksi m ereka. I ngat , pat t ern it u sendiri t idak m endikt e im plem ent asi, hanya dij elaskan sebuah solusi Design. Kit a harus m elaksanakan pat t ern MVC m anapun unt uk Kit a sendiri at au unt uk m enggunakan fram ew ork t hird- part y.

  1 5 .1 .2 Ke u n t u n ga n D e sign pa t t e r n

  Penget ahuan dalam Design pat t ern m em punyai beberapa m anfaat yang nyat a :

  • M e m be r ik a n k om un ik a si ya n g le bih ba ik a n t a r pr ogr a m m e r . Mem punyai

  penget ahuan Design pat t ern m em berikan program m er sebuah kosa kat a baru yang dapat unt uk m engekspresikan m ereka sendiri kepada program m er. Sebagai gant i m enguraikan sebuah m asalah at au solusi secara det ail, program m er dapat m enyebut kan dengan m udah Design pat t ern yang relevan.

  • M e n a m ba h pe n ge t a hu a n ya n g t e la h a da . Mem punyai penget ahuan t ent ang Design

  pat t ern m em biarkan Kit a unt uk m enggunakan solusi dari program m er berbakat sebelum nya. Terdapat sangat banyak Design pat t ern yang t elah didokum ent asikan dim ana Kit a siap m enam bah gudang ilm u penget ahuan Kit a. Pada pem bahasan ini, Kit a akan fokus pada Design pat t ern yang t elah t erbukt i berm anfaat dalam pem buat an aplikasi web.

  1 5 .2 V ie w H e lpe r 1 5 .2 .1 M a sa la h

  Kom ponen- kom ponen View ( biasanya dalam bent uk halam an JSP) um um nya m em iliki kebut uhan akan dat a unt uk present asinya. Bagaim anapun, penyim panan akses dat a logic at au business logic lainnya di dalam sebuah kom ponen present asi m engakibat kan kode m enj adi sulit di- m aint ain dan sedikit sulit unt uk dirubah. I ni dikarenakan set iap perubahan dalam pengolahan dat a akan m engharuskan perubahan- perubahan di dalam layer present asi begit u j uga di layer business. I t u berpot ensi lem ah dalam penggunaan ulang sebuah kode, karena pada dasarnya sat u- sat unya cara unt uk m enggunakan kem bali logic di dalam layer present asi akan m enyalinnya ke dalam kom ponen lain, dengan dem ikian m eningkat kan j um lah kom ponen yang akan dirubah j ika business logicnya dim odifikasi. Juga, m elet akkan business logic di dalam kom ponen present asi m em buat nya m ust ahil unt uk m em iliki sebuah pem isahan t ugas yang j elas ant ara pengem bang soft ware dan Designer web.

  1 5 .2 .2 Solusi

  Unt uk m enghapus pencam puran business logic dari present asi, Kit a m elet akkan logic dalam class " helper" yang t erpisah dim ana bisa didapat kem bali at au di- inst ansiasi oleh kom ponen present asi. Class ini dapat berupa JavaBean at au class t ag cust om . Class helper ini dapat m em ainkan beberapa peran.

  1 5 .2 .3 V ie w H e lpe r s m e m isa h k a n de t a il da r i pe m ba ca a n da t a

  Class helper dapat m em isahkan det ail bagaim ana dat a yang diperlukan didapat kem bali dari penyim panan persist enst at au dari m anapun dalam aplikasi. Layer present asi cukup m em anggil m et hod- m et hod pada helper unt uk m endapat kan kem bali dat a at au m em ilik i helper yang m enghasilkan isi HTML seperlunya.

  Sebagai sat u cont oh skenario, m ari bayangkan Kit a m em punyai sebuah aplikasi yang m em but uhkan unt uk m endaft ar nam a pelaj ar didalam kelas t ert ent u. Cara yang salah unt uk m elakukannya yait u akan m enyim pan logic yang dibut uhkan di dalam sebuah halam an JSP :

  <%@ page import="java.sql.*; javax.sql.*"%> <% // mendapatkan kembali the DataSource DataSource ds = (DataSource)application.getAttribute("applicationDataSource"); Connection conn = ds.getConnection(); Statement stmt = conn.createStatement(); String sql = "SELECT * FROM classlist where classid = "; sql += request.getParameter("classID"); ResultSet rs = stmt.executeQuery(sql); %> The students for class ${params.classID} are : <% while (rs.next()) { %> <li> <%= rs.getString("studentName")%> </li> <% } %>

  Sepert i yang dapat Kit a lihat , yang dihasilkan JSP dari pendekat an ini adalah sedikit berant akan, m eski dengan perm int aan yang sederhana sepert i it u. JSP lainnya yang m ungkin but uh unt uk m endaft ar nam a pelaj ar di dalam sebuah class yang m au t idak m au m enyalin logic di dalam halam an ini unt uk set iap penggunaan ulang.

  Menggunakan pat t ern View Helper, Kit a dapat m em isahkan det ail dat a yang didapat kem bali kedalam suat i JavaBean yang t erpisah : package jedi.sample.bean.helper; public class ClassListHelper { private DataSource ds; private int classID; public void setDataSource(DataSource ds) { this.ds = ds; } public void setClassID(int classID) { this.classID = classID; } public Vector retrieveClassEntries() { if (ds == null || classID = 0) { return null; } Vector returnValue = new Vector(); String sql = "SELECT * FROM classlist where classid = " + classID; Connection conn = ds.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { returnValue.add(rs.getString("studentName")); } return returnValue; } }

  Menggunakan JavaBean t ersebut , kode di dalam JSP akan benar- benar disederhanakan. Daripada m em iliki kode pem bacaan yang t ersim pan di dalam nya, sem ua halam an akan m em er lukan kode unt uk m endapat kem bali sebuah inst ans class helper, kem udian berubah m enj adi nilai- nilai y ang diperlukannya, dan m em anggil m et hodnya.

  <%@taglib uri="http://java.sun.com/jstl/core" prefix="c"%> <jsp:useBean id="helper" class="jedi.sample.bean.helper.ClassListHelper"/> <c:set target="helper" property="classID" value="${params.classID}"/> <c:set target="helper" property="ds" value="${applicationScope.applicationDataSource}"/> The students for class ${params.classID} are : <c:forEach items="${helper.retrieveClassEntries}" var="entry"> <li>${entry}</li> </c:forEach>

  1 5 .2 .4 V ie w H e lpe r s m e n yim pa n da t a m ode l la nj u t a n

  Terkecuali digunakan unt uk m endapat kan kem bali dat a secara langsung dari dalam kom ponen present asi it u sendiri, class helper dapat digunakan unt uk m enyim pan dat a yang t elah dit erim a kem bali oleh kom ponen lain. Dalam kasus ini, class helper berperan sebagai obj ect t ransfer ( lihat Dat a Transfer Obj ect di bawah) .

  Unt uk m enggam barkan ini, Kit a akan m em odifikasi cont oh Kit a sebelum nya. Daripada m endapat kan kem bali dat a secara langsung, m ari Kit a asum sikan bahw a dat a yang Kit a but uhkan t elah dilet akkan ke dalam scope perm int aan oleh sebuah kom ponen yang t erdahulu. Dat a ini m asuk ke form dari JavaBean berikut ini : package jedi.samples.bean.helper; public class ClassListBean { private String[] studentNames; private int classID; public String[] getStudentNames() { return studentNames; } public String getStudentName(int index) { return studentNames[index]; } public void setStudentNames(String[] studentNames) { this.studentNames = studentNames; } public void setStudentName(int index, String studentName) { studentNames[index] = studentName; } public int getClassID() { return classID; } public void setClassID(int classID) { this.classID = classID; } }

  Kit a m em odifikasi JSP kit a sebelum nya unt uk m encerm inkan bean yang berbeda yang kit a gunakan, sepert i j uga m enghilangkan m et hod set t ing param et er : <%@taglib uri="http://java.sun.com/jstl/core" prefix="c"%> <jsp:useBean id="classList" class="jedi.samples.bean.helper.ClassListBean" scope="request"/> The students for class ${classList.classID} are : <c:forEach items="${classList.studentNames}" var="entry"> <li>${entry}</li> </c:forEach>

  1 5 .2 .5 V ie w h e lpe r s m e n ye dia k a n a t a u m e m odifik a si da t a m ode l ya ng t e la h a da

  View helper j uga m em ainkan peran dari adapt er. Yang t erkecuali m am pu unt uk m enyim pan m odel dat a lanj ut an at au m enengah yang yang sebuah view boleh digunakan, m ereka j uga dapat m enyediakan m et hod- m et hod unt uk m enyesuaikan dat a di dalam m odel ket ika view m ungkin dibut uhkan.

  Sebuah cont oh dari penyesuaian dat a yang t elah ada sepert i it u adalah suat u aplikasi yang berbeda for m at . Mari Kit a pert im bangkan sebuah cerit a dim ana Kit a t elah m endapat kan kem bali det ail sebuah t ransaksi sebelum nya. Sepert i inform asi yang akan Kit a t am pilkan, Kit a m enem ukan bahwa j um lah yang t ersedia di dalam sebuah dat a adalah disim pan dalam US Dollar. Bagaim anapun, view m em but uhkan dat a yang dit am pilkan dalam bent uk Peso Filipina. Dalam kasus ini, Kit a dapat m enam bahkan m et hod unt uk view helper dim ana akan m enyesuaikan j um lah dari penyim panan persist ent ke dalam Peso Filipina sepert i yang dibut uhkan oleh View . Cont oh lain dari dar i suat u adapt asi at au penyesuaian yang biasanya dikerj akan oleh view helper adalah penyusunan kem bali it em dat a dalam m odel. Khususnya unt uk daft ar yang panj ang, kem am puan unt uk sort ing sat u field dat a m odel at au lebih m em berikan aplikasi Kit a dengan kem am puan lebih. logic m acam ini dapat disim pan di dalam JavaBean yang berisi m odel dat a.

  Unt uk m enggam barkan konsep ini, Kit a m enggunakan cont oh Kit a sebelum nya. Sebagai gant i m em punyai sebuah St ring sederhana unt uk set iap m asukan daft ar m eskipun dem ik ian, Kit a m enggunakan bean helper di bawah ini : public class Student { private String lastName; private String firstName; private String middleName; // getters and setters untuk properties diatas diletakkan disini }

  Menggunakan bean helper diat as sebagai m odel dat a Kit a m engij inkan Kit a unt uk m em ilih beberapa field- field ket ika sort ing daft ar.

  Kit a m odifikasi bean ClassList Helper sebelum nya yang m enyediakan halam an dengan m et hod yang dapat m em ilih sort ing dat a. Perhat ikan dalam kode di bawah yang ada t anpa im plem ent asi nyat a unt uk sort ing : sort ing yang nyat a t idak fokus dari cont oh Kit a yang disini, t et api lebih bagaim ana Kit a dapat m enggunakan class helper unt uk m em beri fasilit as m ekanism e sort ing di dalam halam an Kit a. package jedi.samples.bean.helper; public class ClassListBean { public static final int LAST_NAME_FIELD = 1; public static final int MIDDLE_NAME_FIELD = 2; public static final int FIRST_NAME_FIELD = 3; private Student[] entries; private int classID; private int sortField = ClassListBean.LAST_NAME_FIELD; // setter dan getter metode dari properties diatas diletakkan disini public Student[] getSortedList() { sortList(); return getEntries(); } public void sortList() { // gunakan property sortField untuk menetapkan field yang mana pada list yang akan // disorting dengan memasukkan implementasi sorting disini } }

  Set elah m enj elaskan class- class helper yang akan Kit a gunakan dalam cont oh Kit a, Sekarang halam an JSP akan m enggunakan m ereka : <%@taglib uri="http://java.sun.com/jstl/core" prefix="c"%> samples.bean.helper.*"/> <jsp:useBean id="classList" class="jedi.samples.bean.helper.ClassListBean" scope="session"/> <jsp:setParameter name="classList" property="*"/> <table> <tr> <td><a href="thisPage.jsp?sortField=<%=ClassListBean.LAST_NAME_FIELD%>"> Last Name </a> </td> <td><a href="thisPage.jsp?sortField=<%=ClassListBean.FIRST_NAME_FIELD%>"> First Name </a> </td> <td><a href="thisPage.jsp?sortField=<%=ClassListBean.MIDDLE_NAME_FIELD%>"> Middle Name </a> </td> </tr> <c:forEach items="${classList.sortedList}" var="entry"> <tr> <td>${entry.lastName}</td> <td>${entry.firstName}</td> <td>${entry.middleName}</td> </tr> </c:forEach> Kem udian, class helper m enyediakan bagian t erbesar dar i peker j aan unt uk pem buat an halam an.

  Sat u- sat unya hal yang dibut uhkan halam an unt uk m engakses fungsi sort ing adalah m enyediakan sebuah param et er field yang m ana adalah daft ar yang disort ing. Pada im plem ent asi di at as, dilaksanakan dengan m enyediakan sebuah link t erhadap dirinya sendiri, dengan nilai yang berbeda unt uk sort ing field. Act ion set Param et er m em asukkan nilai k e dalam class helper, dim ana yang digunakan ket ika m em anggil m et hod get Sort edList ( ) .

  1 5 .3 Se ssion Fa ca de 1 5 .3 .1 M a sa la h

  Selam a pengem bangan berbagai aplikasi, Kit a m em buat sebuah sej um lah obj ect - obj ect yang m em odelkan dom ain m asalah. Obj ect ini berint eraksi sat u sam a lain unt uk m enyediakan fungsi dasar pada aplikasi Kit a. Dalam aplikasi w eb, Kit a biasanya m en- invoke kom ponen Model ini dari dalam sebuah servlet , at au di dalam kasus dari St rut s at au JSF, di dalam act ion handler.

  Mari am bil cont oh sebuah aplikasi banking dengan fungsi unt uk m ent ransfer dana dari sat u account ke account lainnya : public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { // rmendapatkan kembali parameter yang dibutuhkan int sourceAccountID = retrieveSourceAccount(request); int destinationAccountID = retrieveDestinationAccount(request); double amount = retrieveTransferAmount(request); // membuat domain object yang dibutuhkan dalam proses AccountService service = new AccountService(); Account sourceAccount = service.retrieveAccount(sourceAccountID); Account destinationAccount = service.retrieveAccount(destinationAccountID); // memanggil method yang sesuai pada domain object untuk menampilkan fungsi sourceAccount.withdraw(amount); destinationAccount.deposit(amount); service.saveAccountState(sourceAccount); service.saveAccountState(destinationAccount); ...

  } Dalam cont oh ini, Kit a m em iliki sebuah obj ect Account yang berisi inform asi sebuah account khusus, begit u j uga sebuah obj ect Account Service yang m enyediakan fungsi unt uk m endapat kem bali dan m enyim pan account dari dan m enuj u penyim panan persist ent . Sem ent ara pendekat an diat as m em enuhi apa yang dibut uhkan servlet , it u m erupakan beberapa m asalah Design. Pert am a- t am a, m enyediakan sebuah solusi hanya unt uk aplikasi t ert ent u ini. Jik a Kit a m em iliki aplikasi lain yang m em but uhkan fungsi yang serupa, dan Kit a hanya m em ut uskan unt uk m enggunakan lagi kom ponen business yang t elah ada, m au t idak m au Kit a akan m ereplikasi kode diat as di dalam servlet lainnya. Masalah lain dengan pendekat an ini adalah kom ponen yang t idak berm odel ( dalam kasus ini adalah ser vlet ) diper lakukan berlebihan kepada im plem ent asi fungsi dasar sebuah aplikasi. Bagaim ana j ika sebagai cont oh business rule diubah sepert i adanya pem bayaran t am bahan yang diperlukan unt uk t ransfer dana diant ara account - accunt ? Selam a perubahan dapat dit am bahkan pada kode diat as, penanganan det ail sepert i it u seharusnya bukan t anggung j aw ab servlet . Terlepas pert anyaan dari t anggung j awab , j ika Kit a m enam bahkan kode ke servlet ini, Kit a akan m engerj akan m odifikasi yang sam a pada aplikasi m anapun yang m enggunakan fungsi yang sam a. Sebuah m asalah serupa yang kedua adalah bahwa im pelent asi diat as m em but uhkan servlet unt uk m em iliki inform asi obj ect dom ain yang berbeda diperlukan unt uk m engerj akan fungsi dan t et ap m enj aga int eraksi m ereka. Dalam aplikasi yang lebih kom plek, banyaknya obj ect sepert i it u yang bert am bah, m em buat lebih sulit unt uk m e- m aint ain kode client Kit a yang m em but uhkan akses ke fungsi . Juga, hal t ersebut lebih sedikit riskan unt uk berubah : sebagai cont oh, hal t ersebut diput uskan belakangan pada obj ect Account Service adalah unt uk diproses, dengan pem bacaan dan fungsi penyim panan dim asukkan di dalam obj ect Account it u sendiri, perubahan it u m au t idak m au harus m eluas ke sem ua kode client .

  1 5 .3 .2 Solusi

  Solusi m asalah diat as adalah dengan m em buat class t erpisah, sebuah class Facade, yang akan m engenkapsulasi sem ua int eraksi yang diperlukan ant ara obj ect dom ain dan m enam pilkan sebuah int erface yang disederhanakan kepada sem ua client yang m em but uhkan unt uk m engakses fungsi m ereka.

  Unt uk m enggam barkan, berikut ini adalah cont oh sebuah Account Facade : public class TransactionFacade { public transferFunds(int sourceAccountID, int destinationAccountID, double amount) { AccountService service = new AccountService(); Account sourceAccount = service.retrieveAccount(sourceAccountID); Account destinationAccount = service.retrieveAccount(destinationAccountID); // memanggil method yang sesuai pada domain object untuk menampilkan fungsi sourceAccount.withdraw(amount); destinationAccount.deposit(amount); service.saveAccountState(sourceAccount); service.saveAccountState(destinationAccount); } }

  Sekarang, j ika Kit a m em ilik i sebuah aplikasi yang m em but uhkan unt uk m ent ransfer uang ant ar account , sat u- sat unya kode yang perlu diim plem ent asikan kira- kira akan m enj adi sepert i : ... public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { // mendapatkan kembali parameter yang dibutuhkan int sourceAccountID = retrieveSourceAccount(request); int destinationAccountID = retrieveDestinationAccount(request); double amount = retrieveTransferAmount(request); TransactionFacade facade = new TransactionFacade(); facade.transferFunds(sourceAccountID, destinationAccountID, amount); .... }

  Perhat ikan kode client , Kit a dapat m elihat bahwa kode diat as lebih m udah. Unt uk m elaksanakan sebuah t ransfer uang, hanya dibut uhkan m em beri nilai param et er yang sesuai kepada sebuah m et hod. Juga, dengan m em iliki fungsi yang dipisahkan ke dalam class lain, kode client t idak lagi dipengaruhi oleh perubahan dalam business rule at au det ail im plem ent asi.

  Tekecuali dari m anfaat - m anfaat di at as, sekarang lebih sederhana unt uk m enam bahkan sebuah use case kepada aplikasi dalam sebuah cara yang t erorganisasi. Sebagai rev iew , sebuah use case adalah sebuah unit fungsi di dalam sebuah program . Unt uk m enam bahkan sebuah use case kedalam aplikasi Kit a, kit a hanya m engungkapkan sebuah m et hod baru di dalam Facade yang client dapat panggil lalu m em buat im plem ent asinya. Dalam m enerapkan pat t ern ini, adalah pent ing unt uk dicat at bahwa t idak perlu unt uk m em buat sat u class Facade unt uk t iap fungsi yang ingin Anda t unj ukkan. Tergant ung pada kom pleksit as m odel Anda, j uga sebaiknya t idak m enunj ukkan sem ua fungsi Anda hanya m enggunakan Facade. Menggunakan hanya sat u Facade direkom endasikan hanya unt uk aplikasi yang sangat kecil. Apa yang direkom endasikan unt uk kebanyakan aplikasi adalah m engelom pokkan bersam a fungsi yang serupa di dalam sebuah Facade. Jadi, sebuah cont oh, unt uk sebuah aplikasi banking, Kit a dapat m em iliki sebuah Transact ionFacade yang akan m enangani sem ua fungsi adm inist rasi.

  1 5 .4 D a t a Tr a n sfe r Obj e ct s 1 5 .4 .1 M a sa la h

  Akses dat a kepada dan dari sum ber ekst ernal sepert i dat abase relasional at au server LDAP bersifat operasi yang m erugikan : m ereka m enggunakan sum ber t erbat as dan m em but uhkan panggilan- panggilan m elalui j ar ingan dan pat uh kepada kedisplinan j aringan. Biasanya t erdapat operasi di dalam sebuah aplikasi yang m em but uhkan beberapa perangkat yang t erkait dari dat a. Sebagai cont oh, di dalam sebuah aplikasi t oko online, m ungkin ada view t ert ent u at au halam an yang m em but uhkan dat a yang berhubungan dengan nam a, det ail produk, dan ongkos sebuah produk khusus. public class DataRetriever { public String retrieveProductName(int productID) { // menampilkan pembacaan database disini } public String retrieveProductDetails(int productID) { // menampilkan pembacaan database disini } public double retrieveProductCost(int productID) { // menampilkan pembacaan database disini } }

  Jika kit a m em buat pem anggilan t erpisah unt uk set iap set dat a, sepert i yang dit unj ukkan diat as, akan m enghasilkan panggilan ganda kepada sum ber ekst ernal. I ni adalah sesuat u yang ingin Kit a hindari, karena pert im bangan sebelum nya. Beban kinerj a m ungkin t idak akan t erlihat k arena beban yang rendah, t et api unt uk sebuah j um lah user yang t inggi, panggilan- panggilan t am bahan m ungkin m enyebabkan kondisi bot t leneck unt uk kinerj a aplikasi Anda.

  1 5 .4 .2 Solusi

  Unt uk m enghindari pem anggilan ganda pada j aringan, Kit a bisa m endapat kem bali sem ua dat a yang t erkait yang sesuai dengan sekali pem anggilan dan m enyaj ikan dat a it u kepada sisa dari aplikasi m enggunakan sebuah Transfer Obj ect . Obj ect ini m engenkapsulasi set dat a business yang perlu unt uk dit ransfer dari layer ak ses dat a.

  Sebuah sam ple obj ect t ransfer dat a dit unj ukkan di bawah : public class ProductDTO { public String name; public String details; public double amount; public ProductDTO(String name, String details, double amount) { this.name = name; this.details = details; this.amount = amount; } }

  Sepert i yang kit a lihat , t ransfer obj ect adalah class yang sangat sederhana. Sem uanya m enyediakan sebuah const ruct or dim ana m enerim a nilai yang diperlukan ( dit unj ukkan diat as) , at au m ereka m enyediakan m et hod set dim ana m engij inkan program m er unt uk m elet akkan nilai. Apa yang begit u pent ing disini adalah t ransfer obj ect harus m enyediakan sebuah cara unt uk m enyim pan dat a yang diperlukan.

  Menggunakan t ransfer obj ect ini, Kit a dapat m enyederhanakan class Dat aRet riever sebelum nya. Daripada m enyediakan t iga m et hod yang m em but uhkan unt uk dipanggil secara t erpisah unt uk dat a, it u hanya perlu unt uk m enyediakan sat u m et hod m enggunakan t ransfer obj ect sebagai sebuah t ype kem balian. public class DataRetriever { public String retrieveProductName(int productID) { // menampilkan pembacaan database disini } public String retrieveProductDetails(int productID) { // menampilkan pembacaan database disini } public double retrieveProductCost(int productID) { // menampilkan pembacaan database disini } }

  Cont oh dit unj ukkan m endeklarasikan propert ies sebagai public, dim ana m engurangi akses kepada nilai. Jika it u sudah dit ent ukan bahwa beberapa m acam prot eksi dibut uhkan, propert ies dapat dideklarasik an sebagai prot ect ed at au privat e. Transfer obj ect kem udian akan m enyediakan m et hod get sehingga kode lainnya m asih dapat m engakses kepada nilai.

  Di dalam banyak kasus, t ransfer obj ect kit a m ungkin perlu unt uk m em buat isi sem ua at au suat u subset propert ies yang digam barkan dalam obj ect dom ain. Sebagai cont oh, bahw a sangat lah m ungkin bahwa di dalam skenario diat as t elah t ersedia sebuah obj ect Product yang berisi sem ua propert ies yang dibut uhkan unt uk m enj elaskan sebuah inst ance produk di dunia yang nyat a, dim ana nam a, det ail dan isi adalah hanya subset . Dalam kasus ini, akan lebih sesuai unt uk m enggunakan obj ect dom ain it u sendiri, Jadi supaya m enghindari m em buat obj ect lain yang akan m em but uhkan perawat an. Sat u- sat unya pert im bangan yang akan m engarahkan pengem bang- pengem bang unt uk m em buat sebuah t ransfer obj ect t erpisah j ika obj ect dom ain berisi t erlalu banyak det ail yang lain t erkecuali yang diperlukan karena pandangan t ert ent u. Dalam kasus ini, pengem bang boleh m em ilih unt uk m em buat sebuah obj ect t erpisah supaya m engopt im alkan kom unikasi kepada sum ber ekst ernal dan m ent ransfer dat a. Mari kit a sediakan lebih banyak cont oh yang konkrit . Mari kit a pert im bangkan dom ain obj ect berikut ini : public class Student { private String firstName; private String lastName; private String middleName; private String address; private String contactNo; private String courseApplied; private int yearLevel; private Class[] classesTaken; // getters and setters disini

  Terus t erang, sepert inya ada banyak propert ies unt uk sat u obj ect dom ain ini dan kelihat annya sepert i sebuah calon unt uk refact or berikut nya, t et api unt uk sekarang m ari kit a pert im bangkan yang ada. Jika Kit a m em ilik i sebuah halam an JSP yang perlu unt uk m enam pilk an sem ua det ail pelaj ar, akan m enj adi t idak prakt is unt uk m em buat sebuah t ransfer obj ect t erpisah ket ika Kit a dapat m enggunakan obj ect dom ain yang ada. Bagaim anapunm j ika Kit a m em iliki sebuah t am pilan sederhana yang hanya m enam pilkan nam a pelaj ar, it u m ungkin bisa yang t erbaik unt uk m em buat sebuah t ransfer obj ect yang berhadapan dengan hanya sebuah nam a pelaj ar, karena m enggunakan obj ect dom ain asli boleh j adi t erlalu boros di sum ber yang bebannya t erlalu t inggi.

  Terkecuali penggunaannya di dalam m endapat kan kem bali dat a, t ransfer obj ect j uga m em bant u di dalam pengirim an dat a. Pert im bangkan kode di bawah ini : public class DataStorer { public void storeProduct(String productName, String productDetails, double amount) { // implementasi disini } }

  Apa yang m et hod ini arahkan adalah unt uk lakukan pengerj aan sebuah st ore procedure pada sebuah it em produk. Hal t ersebut bekerj a m em erlukan propert ies sebuah produk sebagai param at ernya. Selam a ini bekerj a, bagaim ana akibat nya j ika unt uk beberapa alasan diput uskan oleh t im Design unt uk m odel harga sebuah produk sebagai long daripada double? Bagaim ana j ika banyaknya propert ies yang dibut uhkan sebuah it em produk berubah? Menggunakan t ransfer obj ect daripada daft ar param et er yang fine- grained berfungsi unt uk m em bat asi m et hod t anda t angan Kit a dari perubahan sepert i it u di dalam it em produk, spert i diilust rasikan pada kode dibawah ini : public class DataStorer { public void storeProduct(Product product) { // implementation here } }

  1 5 .5 D a t a Acce ss Obj e ct s 1 5 .5 .1 M a sa la h

  Sem ua aplikasi web m enggunakan dat a dalam prosesnya. Kebanyakan dri m ereka m enggunakan dat a dari penyim panan persist ent disam ping dari berbagai input dari user. Penyim panan persist ent biasanya dim asukkan dalam bent uk dat abase relasional at au file berbasis t eks sepert i file CSV, file XML, at au files sederhana. Beberapa m em but uhkan dat a dari sum ber ekst ernal lainnya sepert i LDAP, at au dari aplikasi bisnis legal. Kit a sudah m elihat bagaim ana m enggunakan JDBC API unt uk m engakses dat abase relasional m enggunakan kode Java. JDBC API m enyediakan sebuah cara st andard m engakses dan m em anipulasi dat abase relasional. Bagaim anapun, m eskipun int erface digunakan unt uk m engakses dat abase it u bisa m enj adi st andard, synt ax yang nyat a dari query SQL susah dilewat kan dari sat u im plem ent asi ke lainnya. Sebuah query SQL yang bekerj a pada sat u dat abase m ungkin t idak bekerj a at au m elaksanakan dengan cara yang berbeda dalam dat abase lain. Sebagai cont oh, dat abase open source Post greSQL m engij inkan m enggunakan operat or ilik e , dim ana m enyediakan perbandingan t ext t idak case sensit if. Operat or ini t idak dikenali secara luas di dalam dat abase Oracle. Kode dibut uhkan unt uk m engakses m ekanism e penyim panan persist ent yang berbeda secara luas. JNDI dapat digunakan unt uk m engakses sum ber LDAP, berbagai processors XML dapat m enangani file XML, dan lain- lain. Mem pert im bangkan perbedaan di dalam im plem ent asi dibut uhkan ant ara perbedaan m ekanism e penyim panan persist enst at au vendor, Kit a dapat m elihat bahwa m enem pat kan kode yang diperlukan unt uk m engakses dat a secara langsung ke dalam k ode client ( servlet ,JSP) akan m enj adi keput usan Design yang dangkal. Selam a it u m em ungkinkan bekerj a pada awalnya, perm asalahan yang akan t erj adi di kem udian j ika di lain hari aplikasi Anda m em but uhkan Anda unt uk pindah ke m ekanism e penyim panan lain at au vendor. Mau t idak m au Anda m enj elaj ah m elalui t iap inci dari k ode aplikasi yang berhubungan dengan pem bacaan dan penyim panan dan m engkonversi m ereka unt uk m enggunakan synt ax baru at au m em but uhkan API .

  1 5 .5 .2 Solusi Solusi disini adalah m em isahkan det ail pem bacaan dat a dan penyim pana dari kode client nyat a.

  I ni dapat diselesaikan dengan m em buat sebuah int erface public yang det ail operasi dat a yang perlu unt uk dit unj ukkan dan m em buat im plem ent asi yang perlu unt uk bekerj a dengan aplikasi sum ber dat a yang ada adalah bekerj a dengannya. Menggunakan solusi ini, j ika pernah m igrasi ke bent uk lain j ika diperlukan, sat u- sat unya hal yang diperlukan adalah unt uk m em buat class lain yang m engim plem ent asikan int erface. Kit a dapat m enggam barkan konsep ini dengan sebuah cont oh.

  Mari Kit a coba bahwa Kit a m em iliki sebuah aplikasi yang m em but uhkan akses ke dat abase unt uk m enangani fungsi relasi usernya, sepert i aut ent ifikasi dan updat e profil. Kit a dapat m enggam barkan operasi dat a dengan int erface berikut : public interface UserDAO { public User authenticateUser(String userName, String password); public void updateProfile(User user); }

  Unt uk m em buat nya bekerj a dengan dat abase relasional, Kit a m enggunakan JDBC API unt uk m em buat sebuah class yang m engim plem ent asikan int erface ini : public UserRDBDAO implements UserDAO { public User authenticateUser(String userName, String password) { String sql = "SELECT * FROM users where username = '" + userName

  • "' and password = '" + password + "';"; DataSource ds = retrieveDataSource(); Connection conn = ds.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); if (rs.next()) { // menerima user data disini dan mengkonversi menjadi object user

  ... } public void updateProfile(User user) { DataSource ds = getConnection(); Connection conn = ds.getConnection(); Statement stmt = conn.createStatement(); stmt.executeUpdate("UPDATE users set username = '" + user.getUsername()

  • "', password = '" + user.getPassword() + "' where userid = " + user.getUserID(); ... }
Maka sekarang, sebagai gant i penem pat an pem bacaan dat a kode secara langsung di dalam kode, Sem uanya yang akan dilakukan adalah m endeklarasikan int erface DAO sebagai ket ergant ungan, m em peroleh sebuah im plem ent asi kem udian m em anggil m et hodnya. public class LoginServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { UserDAO userDAO = new UserRDBDAO(); String userName = request.getParameter("username"); String password = request.getParameter("password"); User user = userDAO.authenticateUser(userName, password); if (user == null) { // memberi tahu user bahwa detail autentifikasi yang cacat telah disediakan } else { // memproses dengan fungsi sebelumnya } } }

  Jika sebagai cont oh m anaj em en bagian at as m em ut uskan unt uk m enyim pan sem ua det ail user di dalam sebuah server LDAP sebagai gant i sebuah dat abase, segala sesuat u yang dibut uhkan unt uk m em buat sebuah im plem ent asi int erface UserDAO yang akan m enerim a kem bali dat a dar i server LDAP dan m enggunakan im plem ent asi t ersebut sebagai gant i im plem ent asi dat abase. public class UserLDAPDAO implements UserDAO { public User authenticateUser(String userName, String password) { // menggunakan JNDI API untuk mendapat kembali detail user return User; } public void updateProfile(User user) { // menggunakan JNDI API untuk meng-update profil user } } public class LoginServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {

   UserDAO userDAO = new UserLDAPDAO();

  String userName = request.getParameter("username"); String password = request.getParameter("password"); User user = userDAO.authenticateUser(userName, password); if (user == null) { // memberi tahu user bahwa detail autentifikasi yang cacat telah disediakan } else { // memproses dengan fungsi sebelumnya } } }

  Sebuah st rat egi yang berm anfaat dalam m enggunakan pat t ern Dat a Access Obj ect unt uk m em buat nya lebih flek sibel dalam perpindahan dat a adalah m enggunakannya di dalam konj ungsi dengan pat t ern Fact ory. Pada dasarnya, sebuah Fact ory adalah class yang bert anggung j awab unt uk pem buat an class lain dan berisi det ail class yang dibuat . Dengan pat t ern Fact ory, kode client hanya perlu unt uk m endeklarasikan int erface sebagai sebuah ket ergant ungan dan m em anggil Fact ory unt uk m enyediakannya dengan im plem ent asi yang perlu. Hal ini m em usat kan set iap kode yang m em ut uskan im plem ent asi m ana yang akan digunakan, m enghindari pengulangan kode dan m em bant u dalam m engurangi m aint ain. Set iap klien yang akan m em erlukan DAO sekarang t idak perlu m enyadari det ail im plem et asi yang m ana yang sedang digunakan. public class DAOFactory { public static UserDAO createUserDAO() { //Jika sebuah database relasional digunakan, membuat sebuah instance dari UserRDBDAO // mengembalikan new UserRDBDAO() //Jika implementasi LDAP , menggunakan DAO yang lain // mengembalikan new UserLDAPDAO(); } } public class LoginServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {

   UserDAO userDAO = DAOFactory.createUserDAO();

  String userName = request.getParameter("username"); String password = request.getParameter("password"); User user = userDAO.authenticateUser(userName, password); if (user == null) { // memberi tahu user bahwa detail autentifikasi yang cacat telah disediakan } else { // memproses dengan fungsi sebelumnya } } }