Wednesday, December 1, 2010

Struktur File, Modul dan Komponen dalam Aplikasi

Di milis id-php ada yang sering kali kesulitan dalam membuat aplikasi yg benar2 loose coupled, walau sudah bikin pake framework pun kayaknya masih belum puas terhadap aplikasi yg di buat. Seringkali ketika membuat modul atau komponen baru, dan dipasangkan ke aplikasi saya tadi, ada saja bagian yang harus disentuh didalam coding.

Pertanyaannya bagaimana kita bisa membuat antar modul atau komponen bisa saling berkomunikasi tanpa memiliki ketergantungan antar modul tersebut.

Thread lengkapnya bisa dibaca langsung di milis. Disini gue ingin menuliskan pandangan gue yang juga gue post disana.

Karena yang bertanya sedang bekerja menggunakan yii framework, banyak pertanyaan yang menuju solusi spesifik di yii framework. Sebelum gue coba jawab, gue disclaimer dulu ya... gue bukan pengguna yii... untuk mencoba mengerti kasus lo, gue coba baca-baca dokumentasi yii.. dan dari situ gue coba mengerti gimana arsitektur aplikasinya. gue bakal berusaha menjawab pertanyaan lo dengan tidak mengesampingkan yii sebagai framework yang udah lo pakai. kalau elo atau teman2 lain ada melihat kesalahan pengertian gue terhadap arsitektur yii.. silahkan dikoreksi..

gue gak akan membahas yii dari sisi technical seperti.. gimana caranya make x atau cara ngejalanin y atau sejenisnya.. tapi lebih ke sisi arsitektur.. tenang... bukan berarti gue gak bahas sama sekali technicalnya.. hanya saja gue akan berusaha kasih contoh atau link.. alasannya gue gak bahas technicalnya dalam2.. ya karena itu... gue gak perna pake yii.. mungkin elo yang biasa pake bisa lebih tahu dari gue.

so gue mulai ya...

ada 2 hal berbeda sebenarnya dari pertanyaan elo. ini mau gue jelaskan terlebih dahulu. supaya gak bingung. yang pertama adalah Arsitektur yang baik dimana kita dapat memiliki komponen/kelas/property yang reuseable antar modul. yang kedua adalah Arsitektur untuk bikin modul yang pluginable.

Ini 2 hal berbeda. dan membuat pembangunan aplikasi memiliki tujuan dan arsitektur yang berbeda. kalo aplikasinya "pluginable" itu artinya aplikasi elo sebenernya bisa ditambahkan third-party komponen (komponen yang ditulis orang lain diluar project aplikasi elo sendiri). Lo jadi harus publikasiin spesifikasi interface elo, supaya orang bisa bikin plugin buat aplikasi elo. dan aplikasi elo sendiri harus dibuat sedemikian rupa supaya siap untuk menerima plugin tersebut entah apa itu pluginnya. karena pada dasarnya bisa apa saja, suka2 orang yang nulis plugin nya.

Kalo gue bole ambil contoh yang dikasih bro Indra, menurut disitu ada beberapa hal yang menyimpang dari konsep plugin itu sendiri. biasanya arsitektur plugin itu gak akan masukin komponen nya langsung kedalam aplikasi utama (copy paste ke directory yang dipakai untuk ngembangin aplikasi utama), umumnya aplikasi utama punya satu directory atau satu pool buat naro plugin, jadi terpisah baik secara fisik maupun konteks dari aplikasi utama. hal yang lain terjadi pada relasi antar object yang "pseudo" dinamis. memang objectnya dinamis. tapi foreign key nya nggak ('user_id'). artinya kalo kebetulan di database atau di object model foreign_key nya bukan 'user_id', tapi misalnya 'person_id' plugin nya gak jalan. ya ini memang bisa diperbaiki hingga semuanya dinamis.. terus tulis spesifikasinya dan lain sebagainya.. tapi Gue pribadi gak gitu yakin kalo ini tujuan dari aplikasi elo.

Kalo baca dari tulisan elo. sepertinya lo cuma butuh untuk tahu gimana Arsitektur yang baik supaya kelas-kelas atau module elo bisa berkomunikasi atau digunakan satu sama lain tanpa memiliki ketergantungan yang erat (loose coupled). semoga asumsi gue benar. dan gue akan menjelaskan tentang ini saja. karena kalo musti ngebahas bikin aplikasi pluginable.. bisa gak selesai-selesai :D

kalo lihat dari arsitekturnya yii framework. yii sudah memberikan kesempatan buat para penggunanya membuat aplikasi yang loose coupled dan high cohesive. gue jelaskan sekali lagi prinsipnya. sebuah kelas/komponen yang baik itu seharusnya loose coupled.. artinya memiliki ketergantungan yang minim antara satu dengan yang lainnya. ketergantungan itu pasti ada, tapi dibuat seminimal mungkin. sebuah kelas/komponen yang baik itu seharusnya high cohesiv.. artinya memiliki satu tujuan atau maksud eksistensi yang jelas.

kalau melihat contoh code yang lo kasih, code elo yang pasti gak kohesiv, karena ada fungsi untuk generate html code di dalam sebuah kelas yang tujuannya adalah sebuah object model.

Dalam hal ini gue pribadi tetep gak ngerti alasan dibalik itu. apa alasannya lo naro fungsi buat generate html di dalam kelas model? gue baca di dokunya, yii punya "component"

kalo liat contohnya kayak gini [TagCloud]

bukankah itu satu code snippet yang generate html untuk digunakan dimana saja? menurut gue konsep ini cukup bagus dan tentunya reuseable. kenapa gak pake ini? ini sudah out of the box dari yii.

lo membuat module dalam yii framework. dengan contoh module siswa dan module kota

kalo baca dari dokumentasinya yii tentang module maka masing-masing module itu seperti aplikasi yang berdiri sendiri (punya view nya sendiri, punya controllernya sendiri, modelnya sendiri, dan lain-lain sendiri)

berarti.. dalam bayangan gue struktur file elo kayak gini
modules/
  siswa/
    SiswaModule.php
    components/
    views/
    controllers/
      DefaultController.php
    extensions/
    models/
      Siswa.php
    views/
    layouts/
    default/
      index.php
  kota/
    KotaModule.php
    components/
    views/
    controllers/
      DefaultController.php
    extensions/
    models/
      Kota.php
    views/
    layouts/
    default/
      index.php

so sekarang lo harus ngerti bahwa secara prinsip arsitekturnya lo gak bisa bikin relasi model antar module. jadi untuk menyatakan bahwa seorang siswa datang dari satu kota, dan dari satu kota datang banyak siswa. masing-masing module harus memiliki modelnya sendiri2. jadi kira2 seperti ini
modules/
  siswa/
    SiswaModule.php
    components/
    views/
    controllers/
      DefaultController.php
    extensions/
    models/
      Siswa.php
      Kota.php
    views/
    layouts/
    default/
      index.php
  kota/
    KotaModule.php
    components/
    views/
    controllers/
      DefaultController.php
    extensions/
    models/
      Siswa.php
      Kota.php
    views/
    layouts/
    default/
      index.php

ini secara prinsip arsitektur loh ya... technically keliatannya bisa saja langsung membuat relasi antar model meskipun model tersebut ada di module
lain. silahkan liat ini atau contohnya mas indra setiawan. dengan menganggap bahwa secara teknis hal ini "mungkin". maka "ketergantungan antar modul" ya jelas tidak dapat dihindari.. udah jelas-jelas disitu lo sengaja bikin relasi model dimana modelnya ada di 2 module yang berbeda.

sekarang anggap saja kita mau mengikuti jalan arsitektur yang benar. kita sadar bahwa 2 model yang sama ada di masing-masing modul. apabila kita punya banyak modul dan di setiap modul kita butuh model siswa, maka model siswa akan ada di setiap modul. ini jelas tidak baik, karena code yang ada ditulis berulang-ulang. dan nantinya sulit untuk di maintain. maka ada baiknya komponen/kelas/model/apa saja yang akan dibutuhkan di semua module, ya ditulis satu kali, dan secara struktur terletak di luar module. gue ngebayangin nya ya kira-kira kayak gini
models/
  Siswa.php
  Kota.php
modules/
  siswa/
    SiswaModule.php
    components/
    views/
    controllers/
      DefaultController.php
    extensions/
    models/
    views/
    layouts/
    default/
      index.php
  kota/
    KotaModule.php
    components/
    views/
    controllers/
      DefaultController.php
    extensions/
    models/
    views/
    layouts/
    default/
      index.php

Sekarang jangan tanya ke gue gimana itu model/komponen/class/apa saja, bisa dikenali oleh masing-masing module kalo ditaro seperti itu :D... pertanyaan technical ini gue balikin ke elo sebagai orang yang lebih sering pake yii.. Tapi sehubungan dengan ini gue juga ingin menjawab pertanyaan elo yaitu:

"Seringkali ketika membuat modul baru, dan dipasangkan ke aplikasi saya tadi, ada saja bagian yang harus disentuh didalam coding."


bagian apa yang harus disentuh dalam coding? bagian terlarang? :D apabila pada awalnya lo cuma punya module siswa.. beserta modelnya.. terus datang kota/kabupaten.. lalu antara siswa dan kabupaten memiliki relasi. ya jelas lo harus aktualisasi model siswa, minimal di bagian relasinya.. untuk menyatakan bahwa siswa ini datang dari kota x. kecuali lo mo bikin unidirectional relation.. yaitu hanya memberikan informasi siswa mana saja yang datang dari kota x. tanpa informasi siswa x datang dari kota mana. maka lo tidak perlu "menyentuh" model siswa.

inipun buat gue sudah minimal.. lo gak akan perlu "menyentuh" controller atau view masing2 module. penyajian viewnya kan beda. kecuali lo misalnya punya view kota yang mau lo attached di view siswa. inipun menurut gue lo sudah punya yii "component" sebagai solusinya.

terlepas dari itu semua.. database design dan domain model design (siswa model, kota model, mungkin sekolah model, beserta relasinya) umumnya sudah di pikirkan atau dipertimbangkan di awal sebelum coding aplikasi. ya gak semua tentunya.. bisa saja tiba2 ada model baru atau konsep baru nongol di tengah jalan.. itu lumrah.. tapi arsitektur yii gak mempersulit hal ini sebenarnya (penambahan model baru, definisi ulang relasi dsbnya). justru mempermudah.

"apakah ngedit script config untuk koneksi modul hal yang wajar?"

ya dan tidak... sekarang kalo lo koneksi databasenya ganti.. harus edit konfigurasi gak?... hayo... :P

yang namanya konfigurasi .. pasti ada saatnya dimana harus di "edit" statement "ya dan tidak" karena kalau dalam hubungan antar code php sendiri, sejak php5, php punya autoloader. dan seperti yang lo liat yii framework juga punya sejenis "autoloader". sejak php5 "autoloader" ini cukup intensif digunakan di setiap jenis framework. tergantung bagaimana frameworknya, atau elo sebagai pengguna framework men setup autoloader ini. bisa saja lo gak harus mengedit configurasi ini lagi sama sekali. umumnya sih autoloader ini bekerja dengan menggunakan naming convention tertentu. kalo di yii kayaknya namanya "namespaces".
// autoloading model and component classes
'import'=>array(
'application.models.*',
'application.components.*',
),

mungkin kalo lo bilang application.* lo gak perlu lagi edit2 confignya.. selama lo gak bikin kelas yang namanya sama :D. kalau di zend framework, ya mereka autoloadernya pake class naming convention. jadi kalo nama kelasnya Barang_Pecah_Belah, maka bisa ditemukan di frameworkpath/Barang/Pecah/Belah.php sekedar contoh.

Pertanyaan dari mas Didin

saya pernah pake cara ini, hal ini kalo menurut saya hampir sama dengan konsep yang di awal dikatakan mas indra untuk membuat core module yang di load setiap saat. cuman, apakah cara ini termasuk ke dalam loose coupled.

atau mungkin dari contoh kasus diatas misal saya mau design aplikasi yang secara simple terdiri dari siswa dan kota. hubungan siswa dan kota seperti biasanya.

kira-kira lebih efisiennya seperti apa? apa dibikin module kota sendiri dan siswa sendiri. atau hanya bikin module siswa dan untuk kota hanya dibuatkan model yang diletakan di model utama (core module).

untuk masalah high cohesive tadi, tujuan saya membuat method di class sebelumnya. untuk membuat element select yang nantinya bisa dimasukan ke dalam variable javascript. kenapa saya gak pake helpernya Yii (CHtml)?? karena helpernya yii menggenereate select dengan menyertakan format enter "\n" (mohon koreksi kalo seandainya pemahaman saya salah). yang kalo seandainya dimasukan ke dalam variabel di javascript akan error. makannya sya bikin method sendiri.

pada dasarnya kalo lo ngikutin arsitekturnya yii.. semua model, view, controller, component dan lain2 nya yii itu sudah cukup loose coupled. kalo lo mo lebih loose coupled lagi, lo musti kerja pake interface, punya class factories atau pake inversion of control container dll.. dimana yii sendiri gak mensupport itu out of the box, dan gue gak yakin lo butuh saat ini.. yang penting kan make yii dulu yang bener toh bukan begitu?

Dan ingat prinsip autoloader itu gak nge "load semua".. autoloader itu cuma ngeload waktu lo butuh.. jadi pas lo new Siswa() atau Siswa:: atau sejenisnya baru di load. kalo gak dibutuhkan gak di load.

gue lihat.. bekerja pake yii itu gak harus pake module. kalo lo liat contoh2 disini


itu contohnya semua gak kerja pake module. kalo dalam definisi yii itu istilahnya "default" module. kalo mo beneran pake module kan di dalam protected itu ada directory module, dimana di dalam directory module itu ada directory nama module nya (dalam doku contohnya forum) dan di dalam directory tersebut ada model, view controller component dll. sedangkan dalam contoh di link tersebut gak seperti itu.

antara gue gak ngerti bener tujuan aplikasi lo.. atau lo belum begitu ngerti kenapa orang bikin "module".. bikin aplikasi yang modular kadang gak selalu langsung bikin "module" :D dan apakah pengertian "core module" elo dengan prinsip "default module" nya yii itu sama.. gue juga gak tahu.. hehehe tapi mungkin mengenai module ini gue coba luruskan dulu...

seperti yang gue bilang sebelumnya atau sesuai dokunya yii.. module itu konsepnya satu aplikasi utuh. di dokunya mereka ambil contoh forum. biasanya kalo lo punya aplikasi yang besar. katakanlah lo punya webportal namanya "didin".. lo punya cms untuk portal beritanya, terus lo punya forum buat orang2 nongkrong.. terus lo punya online shopping.. dll...

masing2 punya kompleksitasnya sendiri2... kompleksitas spesifik ini yang menjadi tujuan module. banyak logik2 yang gak dibutuhkan atau gak berhubungan satu sama lain. apabila ini dijadiin satu, hanya merepotkan maintenance nya saja. ya.. ada satu point dimana ada hal-hal yang dipakai bareng.. katakanlah login information. hal hal seperti ini ya seperti yang gue bilang sebelumnya.. sebaiknya di taruh atau exist di luar module ini.

sekarang lo harus coba bertanya pada diri lo sendiri.. seberapa kompleks aplikasi saya? atau seberapa kompleks "siswa" atau "kota" sampe2 harus dibikin masing2 sebagai module? kalo tujuannya cuma pengen bikin satu data grid dimana cuma kasih liat siswa mana saja yang datang dari kota x? kayak gini mah gak perlu module.

lo cuma butuh 2 activerecord model. 1 controller dan 1 view... sekompleks2nya tambah satu form model.. sudah cukup...

1 active record model buat siswa, 1 buat kota.. masing2 kasih relasinya 1 controller kasih satu action. dan bikin gridnya di view.

kalo perlu tambahin form supaya bisa masukin nama kotanya.. biar grid siswanya dinamis.. sudah toh? gak perlu module.

mungkin lain ceritanya ya kalo mo bikin .... *mikir*... entahlah... aplikasi untuk pemerintah propinsi kali ya.. dimana lo punya satu bagian tentang "sekolah" dari urusan management nya, keuangannya, mungkin siswa dan pegawainya.. inventarisasi dlsbnya.. dan lo punya bagian lagi tentang "daerah" dari informasi pemerintahnya (kepala daerah, pegawai pemerintah) tata kota, akta-akta dan lain sebagainya. ini mungkin layak lo bikin satu modul sekolah dan satu modul daerah. dan kalo lo mo bikin hubungan "siswa" dan "kota" ya model dari kedua module tersebut harus selayaknya ada di luar module.

mengenai Chtml, gue gak bisa komentar karena gue gak tahu gimana cara kerjanya.. bahwa chtml ga bisa lo pake, menurut gue bukan alasan bahwa itu html select lo generate di satu method dalam sebuah active record class :D gue yakin itu method buat generate select pasti bisa lo taro di tempat lain.. yang pasti bukan di active record tempatnya. menurut gue itu yii component konsepnya sesuai. contohcomponent gue sempat kasih linknya.

No comments: