Feeds:
Posts
Comments

Archive for the ‘Teknologi Informasi’ Category

Blogger datang dan pergi.

Blogger datang, menulis, memeras inspirasi untuk eksis dalam hiruk pikuk blog. Satu bulan, dua bulan, tiga bulan, akhirnya satu tahun, dua tahun dan seterusnya. Beberapa kemudian pergi, tidak kembali. Mungkin kehabisan inspirasi setelah diperas habis-habisan untuk ditulis. Beberapa terus terus eksis, seperti tidak pernah kehabisan inspirasi, seperti sumur dengan sumber air yang seolah tidak pernah habis ditimba, keluar dan keluar terus menerus menghasilkan tulisan.

Peristiwa demi peristiwa datang silih berganti, ditulis, dikomentari, dikritik, didukung, diperjuangkan blogger dalam kata-kata, dengan persepsi masing-masing. Ada yang netral, ada yang mengikuti pasar, ada yang seia sekata, ada yang menerobos pagar dan melawan, ada yang obyektif, ada yang subyektif. Semua ditulis sesuai dengan pemahaman dan kata hati.

Blogger datang dan pergi.

Berkunjung, berkomentar, meninggalkan jejak, membangun hubungan dan silaturrahim sesama blogger, saling membantu, tepo seliro, anggah ungguh, sopan santun dibangun dan dijunjung. Artikel ditulis, jejak ditinggalkan, dikunjungi, dikomentari, dan terciptalah simpul unik silaturrahim. Saling memberi dan saling berbagi, berbagi ilmu mencipta wawasan.

Blogger datang dan pergi.

Satu blog tidak cukup. Ditambah lagi, lalu tambah lagi, dan tambah lagi. Satu dot com, dua dot com dan bertambah lagi dot com dot com yang lain. Domain dan hosting dibeli. Semua dengan jejak, penunjuk arah dan peta, jalan dan link agar mudah dikunjungi.

Blogger datang dan pergi.

Saat datang apakah kita peduli? Saat pergi apakah kita peduli? Blogger datang dan pergi. Hari ini datang, apakah juga akan pergi?

Ditulis sebagai pengantar dan pembuka jalan menuju blog baru, http://butirpasirku.wordpress.com

Hiatus, vakum, inactive, cuti dan entah apa lagi. Sudah sekian lama waktu, saya tidak aktif dari dunia blog. Tidak menulis, tidak blog walking, dan tidak komen di mana-mana. Semuanya berhenti, meskipun masih ada satu dua nafas kehidupan di blog ini. Satu bulan sekali, saya mencoba untuk memberi nafas kehidupan pada blog ini, dengan menulis apa adanya.

Satu persatu, pengunjung yang dulu sering memberi komentar di sini, mulai hilang. Tapi backlink yang dan jejak yang dulu saya tinggalkan di blog-blog yang pernah saya kunjungi, masih menghasilkan kunjungan, setidaknya satu dua kunjungan. Memang resiko, bahwa blog tanpa blog walking seperti makan tanpa lauk, seperti event tanpa publishing, seperti produk tanpa iklan, dan pastinya akan sepi dari hiruk pikuk dan hingar bingar perblogan.

Lalu kenapa harus membuat blog lagi? Entahlah, mungkin sekedar tajdid an-niyah, memberparui niat. Setidaknya, dengan blog baru saya menghasilkan moment dan niat baru untuk menulis. Terlebih, ketika ketika saya ingin menulis, sering saya merasa tidak sreg untuk dipublish di sini. Blog yang pada mulanya saya isi dengan artikel-artikel teknologi informasi, telah bergeser pada tema-tema yang lebih sederhana dan mudah dipahami, dan menjadi personal blog yang bersifat umum.

Artikel-artikel yang saya publish di http://butirpasirku.wordpress.com berbeda dengan blog ini. Beberapa artikel saya boyong dari sini, terutama artikel-artikel lama yang berhubungan dengan teknologi informasi. Teknologi informasi? Ya, http://butirpasirku.wordpress.commemang saya buat untuk mempublish uneg-uneg seputar kehidupan dan pekerjaan sehari-hari, terutama yang berhubungan dengan dunia IT dan tidak mungkin dipublish di sini. Dunia IT memang segmented, dan tidak umum. Karenanya, saya merasa perlu untuk memisahkannya dari sini, agar blog ini, tetap dengan tulisan-tulisan sederhana yang mudah dipahami.

Wa ba’du. Saya tidak tahu apakah bisa konsisten menulis atau tidak. Tapi, saya tetap ingin menulis disela-sela perasaan malas, diantara pekerjaan dan hidup yang terus berjalan. Setidaknya sebulan sekali, dua bulan sekali, atau bahkan setahun sekali, saya akan mengupdate blog ini.

Read Full Post »

Selama beberapa hari ini saya masih merasa impressif dengan CakePHP, meskipun sebelumnya lebih banyak menggunakan CodeIgniter. Aneh, ketika banyak orang lebih senang dengan CodeIgniter, saya justru terkesan dengan pola pengembangan menggunakan CakePHP, dengan aturan main yang sangat ketat. Jauh berbeda dengan CodeIgniter yang longgar aturannya, karena CakePHP lebih murni MVC. Pada CodeIgniter, apapun bisa dilakukan di model, view maupun controller. Bahkan, saya pernah membuat library abal-abal yang ada SQLnya. Meskipun mudah, tapi saya merasa kurang nyaman dengan kelonggaran yang diberikan CodeIgniter. Bahkan, query builder (active record) CodeIgniter, bisa dieksekusi pada controller. Dengan pengembangan seperti ini, jumlah baris kode controller menjadi sangat banyak. Ujung-ujungnya, membingungkan maintenance. Belum lagi ketika bicara standard pengembangan. Wah, untuk pengembangan yang tidak kecil jangan menggunakan CodeIgniter lah sebaiknya. Pergantian programmer, selalu diikuti dengan pergantian style coding. Begitu terjadi pergantian programmer sampai sepuluh kali, hampir dipastikan programmer terakhir bakalan mabok melakukan maintenance code yang nggak karuan stylenya.
Kasus seperti inilah yang bisa diminimalisir oleh CakePHP. Perhatikan baris code berikut:

class CategoriesController extends AppController {
	function add() {
		if ( !empty ( $this->data ) ) {
			$this->Category->create();
			if ($this->Category->save($this->data)) {
				$this->Session->setFlash(__('The Category has been saved', true));
				$this->redirect(array('action'=>'index'));
			} else {
				$this->Session->setFlash(__('The Category could not be saved. Please, try again.', true));
			}
		}
	}
}

Penamaan controller dalam CakePHP sudah ada aturannya. Ini memiliki benang merah dengan penamaan model. penamaan fungsi, memiliki benang merah dengan nama view. Semua jelas aturannya, dan harus sesuai dengan convention agar bisa bekerja.
Sekarang perhatikan baris

$this->Category->save($this->data);

Baris inilah yang membuat saya sangat terkesan dengan CakePHP. ORM benar-benar membantu melakukan operasi yang berhubungan dengan database. Semua relasi dipetakan, dan tinggal dicomot untuk digunakan. Bahkan, validasi form bisa dilakukan dengan sangat sederhana, hanya mendefinisikan array di model, dan semua sudah bekerja. What do we expect more?
Bagaimana dengan Yii? Saya mencobanya hari ini, dan begitu melihat bagaimana code dibangun dengan Yii, saya langsung pesimis. Meskipun hasil test performance luar biasa, mengungguli CakePHP dan CodeIgniter, tapi style code yang ditawarkan tidak saya sukai. Selain itu, berdasarkan pengalaman, performance aplikasi lebih banyak dipengaruhi oleh database query dari pada rendering halaman PHP.
Perhatikan contoh code controller berikut untuk membuat hello world:

class SiteController extends CController
{
	public function actionIndex()
	{
		echo 'Hello World';
	}
}

Hehehe, ini adalah baris code pertama yang saya lihat di Yii, dan langsung membuat saya pesimis untuk menggunakannya. CakePHP tidak akan mengizinkan hal serupa terjadi. Output hanya bisa digenerate lewat view, dan controller murni berisi business logic. Sebagian programmer cenderung lebih menyukai model coding seperti ini di CodeIgniter maupun Yii, karena bebas dan leluasa melakukan coding. Boleh dan sah-sah saja. Tapi untuk pengembangan skala kecil.
Bagaimana dengan pengembangan skala menengah sampai besar? Hal yang harus diingat dalam pengembangan skala menengah dan besar adalah konsistensi pengembangan jangka panjang dan maintenance yang membutuhkan code convention (aturan code) yang baku. Dalam hal ini, CakePHP lebih menjanjikan, karena memang convention dalam CakePHP jauh lebih ketat. Aturan penamaan class, fungsi, file naming, form handling, dan sebagainya sudah baku. Bahkan, penempatan file pendukung seperti file JavaScript, CSS, image, external resource, component, library, template, layout dan sebagainya sudah ditentukan. Aturan-aturan seperti ini akan sangat membantu untuk pengembangan dan maintenance jangka panjang, karena programmer, dengan style apapun, dipaksa mengikuti aturan main yang sudah ditentukan oleh framework. Standard inilah yang juga harus diikuti oleh programmer-programmer yang baru bergabung.
Sampai saat ini, selain ORM dan auto generate code , convention yang ditawarkan oleh CakePHP benar-benar membuat saya nyaman untuk memulai pengembangan project baru. Untuk ke depannya, saya sudah tidak perlu lagi cuap-cuap jika ada programmer baru, tinggal menyuruhnya mempelajari CakePHP, dan saya bisa tidur dengan nyaman

Read Full Post »

Perkenalan dengan Bake pada CakePHP yang fantastis kemarin, berlanjut pada pada project kecil untuk memahami behavior pada framework ini. Untuk lebih mudahnya, saya menyebutnya project ‘Friend.’ Tujuannya sederhana, bisa melakukan operasi CRUD pada table independent (tidak memiliki relasi dengan table yang lain).
Controller, memiliki aturan penamaan file dengan namacontroller_controller.php yang diletakkan dibawah directory /root/my_cake/controllers.
Berikut ini isi file /root/my_cake/controllers/friends_controller.php yang saya buat:

 
< ?php
class FriendsController extends AppController {
	
	function index() {
	}
}
?>

View, memiliki aturan penamaan file dengan extensi .ctp. Untuk controller diatas, yang tidak didefinisikan viewnya, secara default akan menampilkan view sesuai dengan nama fungsi (dalam hal ini index) dibawah direktori ‘namacontroller’ yang dalam project ini bernama ‘friends’ dibawah directory /root/my_cake/views.
Berikut ini isi file view yang saya buat (/root/my_cake/views/friends/index.ctp):

Hello World…

Hasilnya adalah sebagai berikut (diakses dari url http://localhost/my_cake/friends):
(more…)

Read Full Post »

Santai, buka file

/etc/default/rcs

terus, set disable UTC menjad

UTC=no

terus direstart kompinya. Bisa juga diganti pake perintah

hwclock --hctosys

gara-gara ini server nggak pernah bener waktunya setiap kali restart

Read Full Post »

Malam ini mencoba CakePHP karena tertarik dengan dua hal, yang pertama ORMnya dan yang kedua fasilitas Bake yang memberikan auto generate code. Dengan aturan-aturan tertentu saat pembuatan table, ternyata apa yang dijanjikan CakePHP sebagai RAD (Rapid Application Development) memang benar. I had to say it’s great. Benar-benar luar biasa.
Bake membaca table dalam database, yang kemudian dipetakan untuk dijadikan Model, View, dan Controller. Semua langsung jadi, hanya tinggal mengikuti aturan main dalam pembuatan database. Sebelumnya fasilitas serupa saya temukan di qcubed, namun melakukannya pada ORM.
Berikut ini contoh table dengan aturan relasi yang dimaksud dalam cake:

CREATE TABLE `categories` (
	`id` int(10) NOT NULL auto_increment,
	`name` varchar(50) default NULL,
	PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `posts` (
	`id` int(10) NOT NULL auto_increment,
	`title` varchar(100) default NULL,
	`content` text,
	`created` datetime default NULL,
	`updated` datetime default NULL,
	`category_id` int(10) default NULL,
	PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Table ‘posts’ memiliki relasi ke table ‘categories,’ yang direpresentasikan pada ‘category_id’. Nama table harus bentuk plural seperti ‘posts’, ‘categories’. Foreign key harus menggunakan namatable_id, yang mana ‘namatable’ akan merujuk pada nama table dan dan ‘id’ adalah aturan dalam cake. Pada table ‘posts’ berbentuk kolom ‘category_id’.

Dengan model aturan seperti itu, auto generate code sudah menghasilkan model, view dan controller secara otomatis dengan Bake. Saya jadi paham mengapa CakePHP memang ditujukan untuk Rapid Application Development. Dan ternyata pengembangan yang saya lakukan selama ini bukan rapid development, tapi stupid development

Tutorial yang saya gunakan download disini

Catatan:
Saya menggunakan wamp server versi 2.0
Perintah

cake bake all

diganti dengan

cake -app C:/wamp/www/caketest/ bake all

file

cake.bat

isinya diedit sehingga menjadi seperti berikut:

@echo.
@echo off

SET app=%0
SET lib=%~dp0

c:\wamp\bin\php\php5.2.8\php.exe -q "%lib%cake.php" -working "%CD%" %*

echo.

Thanx to irfaniYangBaikHati untuk tutorialnya 🙂

Read Full Post »

Pas blog walking, tiba-tiba saya ingat blog dosen saya dulu, Ardiansyah yang sukses dengan software MyFamily Accounting. Ada artikel menarik tentang trend TA mahasiswa TI UAD yang ditulis tahun 2007 (berarti saya belum lulus), yang saking banyaknya akhirnya malah dilarang. Lha Mungkin semua TA seperti itu, jadi kelihatan tidak innovative. Keluhan yang wajar saya pikir, ketika semua TA hanya seperti itu-itu saja.
Saya pribadi bisa memahami arah tulisan tersebut, tentang kejenuhan dan sebagainya. tapi kita juga tidak boleh lupa bahwa S1 tetap S1, tidak lebih. Boleh lah berapologi tentang project open source dan sebagainya, sah2 saja. Tapi ingat, kondisi akademis masih belum mendukung. Lagian, belum ada dosen yang memang concern terhadap pengembangan software. MyFamily Accounting pun programmernya juga mahasiswa, meskipun ‘bos’ nya adalah dosen. Makanya, ketika berharap lebih terhadap para mahasiswa, kenapa dosen tidak berkaca dulu? Hal baik, dimulai dari diri sendiri, termasuk tentang TA yang open source tadi. Itu point pertama.

Kedua, teknologi itu harusnya little thing works miracle. Apapun teknologinya, selama bisa membuatnya works miracle, that’s fine. Jadi jangan dilihat teknologinya, tapi lihat manfaatnya. Ingat, riset2 kecil dalam pengembangan software kesehatan. Teknologinya sederhana, tapi works miracle. MyFamily Accounting sendiri pun saya pikir memiliki prinsip yang sama. So, kenapa dipermasalahkan tentang teknologi database tadi? Toh tidak melenceng dari disiplin akademik OODB? Justru aneh kalau dilarang karena diajarkan.

Ketiga, teknologi itu menjadi sederhana kalau kita tahu cara kerjanya. Apa sih yang hebat dari teknologi desktop, internet, games, networking, multimedia, user interface, kernel, security berbasis KDE, GNOME, maupun project-project di sourceforge.net itu jika kita tahu teknologinya? biasa saja, tidak ada yang istimewa, sama tidak istimewanya dengan sistem informasi database tadi. jadi apakah teknologi itu nanti akan dilarang juga jika sudah jenuh? That’s a matter right?

So, let’s get down to the earth. Technology is just a technology. look at facebook, it’s not about technology, but how it works miracle 🙂

Read Full Post »

MABOK QUERY

Ini ‘ringkasan’ query hari ini, disebut ringkasan karena hanya ringkasan saja, beberapa subquery sudah dihapus. Masalahnya, subquery model di bawah ini sepertinya memperlambat executed time. Mungkin ada yang punya tuning guide untuk model query seperti ini? (mabok)

SELECT 
	rl2.rl_id AS id, 
	rl2.dtd, rl2.icd10, 
	rl2.diagnosis,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND DATEDIFF(DATE(adm.admission_dttm),DATE(per.birth_dttm)) BETWEEN 0 AND 28 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml28hr,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND DATEDIFF(DATE(adm.admission_dttm),DATE(per.birth_dttm)) BETWEEN 28 AND (365-1) 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml1th,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND DATEDIFF(DATE(adm.admission_dttm),DATE(per.birth_dttm)) BETWEEN 365 AND (5*365-1) 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml4th,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND DATEDIFF(DATE(adm.admission_dttm),DATE(per.birth_dttm)) BETWEEN (5*365) AND (15*365-1) 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml14th,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND DATEDIFF(DATE(adm.admission_dttm),DATE(per.birth_dttm)) BETWEEN (15*365) AND (25*365-1) 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml24th,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND DATEDIFF(DATE(adm.admission_dttm),DATE(per.birth_dttm)) BETWEEN (25*365) AND (45*365-1) 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml44th,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND DATEDIFF(DATE(adm.admission_dttm),DATE(per.birth_dttm)) BETWEEN (45*365) AND (65*365-1) 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml64th,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND DATEDIFF(DATE(adm.admission_dttm),DATE(per.birth_dttm)) > (65*365-1) 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml44th,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND per.adm_gender_cd = "m" 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml_m,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND per.adm_gender_cd = "f" 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jml_m,
	(	SELECT 
			COUNT(*) 
		FROM 
			xocp_ehr_admission_diag dg 
			INNER JOIN xocp_ehr_con2rl2 con ON dg.obj_id = con.concept_id 
			INNER JOIN xocp_ehr_patient_admission adm USING(patient_id, admission_id) 
			INNER JOIN xocp_ehr_patient pat USING(patient_id) 
			INNER JOIN xocp_persons per USING(person_id) 
		WHERE 
			con.rl_id = id 
			AND adm.status_cd != "nullified" 
			AND pat.status_cd != "nullified" 
			AND per.status_cd != "nullified" 
	) AS jmlall 
FROM 
	xocp_ehr_rl2 rl2 
ORDER BY 
	jmlall DESC

Read Full Post »

Older Posts »