Advertisement
  1. Code
  2. ActionScript

Apa itu Configuration Object, dan Mengapa Repot Menggunakannya?

Scroll to top
Read Time: 9 min

() translation by (you can also view the original English article)

Sungguh menyakitkan harus mengubah parameter fungsi; Anda harus mengubah setiap panggilan lain ke fungsi itu untuk menghindari kesalahan. Tetapi Anda dapat menyiasatinya dengan menggunakan hanya satu parameter: obyek konfigurasi.


Seperti Ini Rupanya

Berikut ini contoh konyol dari fungsi untuk membuat robot:

1
2
function generateRobot(arms:int, personality:String):Robot {
3
  var robot:Robot = new Robot();
4
	
5
	for (var i:int = 0; i < arms; i++) {
6
		//create arm and add it to robot

7
	}
8
9
	if (personality == "evil") {
10
		robot.commands = "Destroy mankind.";
11
	}
12
	else {
13
		robot.commands = "Bake cookies."
14
	}
15
	return robot;
16
}
17
18
generateRobot(2, "evil");

Sekarang, inilah contoh yang sama, menggunakan obyek konfigurasi:

1
2
function generateRobot(conf:Object):Robot {
3
	var robot:Robot = new Robot();
4
	
5
	for (var i:int = 0; i < conf.arms; i++) {
6
		//create arm and add it to robot

7
	}
8
9
	if (conf.personality == "evil") {
10
		robot.commands = "Destroy mankind.";
11
	}
12
	else {
13
		robot.commands = "Bake cookies."
14
	}
15
	return robot;
16
}
17
18
generateRobot({arms:2, personality:"evil"});

Saya telah menyoroti baris yang perlu diubah; Anda dapat melihat bahwa tidak ada banyak perbedaan.


Mengapa Repot-repot?

Jadi jika hampir tidak ada perbedaan, mengapa kita repot-repot melakukannya dengan cara kedua? Bagaimanapun, itu sebenarnya membuat fungsi sedikit lebih sulit untuk digunakan; sedangkan sebelum IDE kami dapat memberi kami informasi tentang parameter yang diharapkan fungsi:

...sekarang hanya bisa memberi kita ini:

Misalkan Anda ingin menambahkan beberapa parameter lagi: satu menentukan bahan yang akan digunakan dan yang lain untuk menentukan warna laser yang seharusnya. Itu tidak terlalu sulit, dalam kedua kasus:

1
2
function generateRobot(arms:int, personality:String, material:String, laserColor:String):Robot {
3
	var robot:Robot = new Robot();
4
	
5
	for (var i:int = 0; i < arms; i++) {
6
		//create arm and add it to robot

7
	}
8
9
	if (personality == "evil") {
10
		robot.commands = "Destroy mankind.";
11
	}
12
	else {
13
		robot.commands = "Bake cookies."
14
	}
15
16
	switch (material) {
17
		case "wood":
18
			//wooden robot

19
		break;
20
		case "steel":
21
		default:
22
			//steel robot

23
		break;
24
	}
25
26
	robot.laser = new Laser();
27
	robot.laser.color = laserColor;
28
29
	return robot;
30
}
31
32
generateRobot(2, "evil", "steel", "red");
1
2
function generateRobot(conf:Object):Robot {
3
	var robot:Robot = new Robot();
4
	
5
	for (var i:int = 0; i < conf.arms; i++) {
6
		//create arm and add it to robot

7
	}
8
9
	if (conf.personality == "evil") {
10
		robot.commands = "Destroy mankind.";
11
	}
12
	else {
13
		robot.commands = "Bake cookies."
14
	}
15
16
	switch (conf.material) {
17
		case "wood":
18
			//wooden robot

19
		break;
20
		case "steel":
21
		default:
22
			//steel robot

23
		break;
24
	}
25
26
	robot.laser = new Laser();
27
	robot.laser.color = conf.laserColor;
28
29
	return robot;
30
}
31
32
generateRobot({arms:2, personality:"evil", material:"steel", laserColor:"red"});

Sejauh ini, masih tidak banyak perbedaan. Bagaimana jika Anda ingin semua robot memiliki laser merah? Sederhana lagi. Tanpa obyek konfigurasi, Anda hanya perlu mengubah metode signature (baris function), dan kemudian Anda dapat menghapus argumen terakhir dari panggilan fungsi:

1
2
function generateRobot(arms:int, personality:String, material:String, laserColor:String = "red"):Robot {
3
    //this is all the same

4
}
5
6
generateRobot(2, true, "steel");    //I removed the last argument

Dengan obyek konfigurasi, ini sedikit rumit - meskipun tidak banyak:

1
2
function generateRobot(conf:Object):Robot {
3
	if (!conf.laserColor) {
4
		conf.laserColor = "red";
5
	}
6
7
	var robot:Robot = new Robot();
8
	
9
	for (var i:int = 0; i < conf.arms; i++) {
10
		//create arm and add it to robot

11
	}
12
13
	if (conf.personality == "evil") {
14
		robot.commands = "Destroy mankind.";
15
	}
16
	else {
17
		robot.commands = "Bake cookies."
18
	}
19
20
	switch (conf.material) {
21
		case "wood":
22
			//wooden robot

23
		break;
24
		case "steel":
25
		default:
26
			//steel robot

27
		break;
28
	}
29
30
	robot.laser = new Laser();
31
	robot.laser.color = conf.laserColor;
32
33
	return robot;
34
}
35
36
generateRobot({arms:2, personality:"evil", material:"steel"});   //I removed the last argument

Baiklah. Sekarang anggaplah Anda menemukan bahwa Anda mengatur hampir semua robot Anda menjadi jahat (maksud saya, mengapa tidak?), jadi sebenarnya agak merepotkan untuk menulis "kejahatan" sebagai parameter setiap waktu. Secara alami, Anda ingin mengatur "jahat" sebagai default - tetapi Anda tidak ingin mengatur materi default.

Satu-satunya cara Anda dapat melakukan ini, dengan seperangkat parameter fungsi biasa, adalah dengan mengubah urutan parameter personality dan material:

1
2
function generateRobot(arms:int, material:String, personality:String = "evil", laserColor:String = "red"):Robot {

Ah, tapi sekarang Anda harus mengganti urutan putaran argumen pada setiap panggilan fungsi tunggal!

1
2
generateRobot(2, "evil", "steel");    //no longer works

Obyek konfigurasi tidak memberi Anda masalah ini. Coba lihat:

1
2
function generateRobot(conf:Object):Robot {
3
	if (!conf.laserColor) {
4
		conf.laserColor = "red";
5
	}
6
	if (!conf.personality) {
7
		conf.personality = "evil"
8
	}
9
10
	//this is all the same

11
}
12
13
generateRobot({arms:2, material:"steel"});  //no "personality" parameter? no problem!

Rapi! Semua panggilan fungsi generateRobot() lama Anda akan terus berfungsi, tetapi Anda dapat membuat panggilan baru yang tidak mengganggu dalam menentukan personality.

Anda bahkan dapat memutuskan untuk menghapus parameter personality sekaligus:

1
2
function generateRobot(conf:Object):Robot {
3
	if (!conf.laserColor) {
4
		conf.laserColor = "red";
5
	}
6
	if (!conf.personality) {
7
		conf.personality = "evil"
8
	}
9
10
	var robot:Robot = new Robot();
11
	
12
	for (var i:int = 0; i < conf.arms; i++) {
13
		//create arm and add it to robot

14
	}
15
16
	robot.commands = "Destroy mankind.";
17
18
	switch (conf.material) {
19
		case "wood":
20
			//wooden robot

21
		break;
22
		case "steel":
23
		default:
24
			//steel robot

25
		break;
26
	}
27
28
	robot.laser = new Laser();
29
	robot.laser.color = conf.laserColor;
30
31
	return robot;
32
}

Versi fungsi di atas sama sekali tidak merujuk ke conf.personality - tetapi Anda tidak akan mendapatkan kesalahan jika Anda masih memiliki panggilan seperti ini:

1
2
generateRobot({arms:2, personality:"evil", material:"steel"});

Tentu saja, Anda mungkin mendapatkan beberapa pengguna yang bingung jika ada panggilan seperti ini:

1
2
generateRobot({arms:2, personality:"good", material:"steel"});

...karena semua robot sekarang jahat. Tetapi setidaknya kode akan dikompilasi.

Untuk alasan yang sama, Anda dapat mengubah urutan argumen tanpa masalah sama sekali, dan bahkan menambahkan parameter baru yang belum melakukan apa pun:

1
2
generateRobot({material:"steel", laserColor:"green", arms:2, voice:"Mr. T"});

Membuatnya Lebih Mudah untuk Mengatur Default

Kode untuk pengaturan default mudah dipahami sejauh ini, tetapi akan sangat menjengkelkan untuk memperpanjang jika kita perlu memiliki banyak parameter:

1
2
	if (!conf.laserColor) {
3
		conf.laserColor = "red";
4
	}
5
	if (!conf.personality) {
6
		conf.personality = "evil"
7
	}

Mari kita menulis beberapa kode yang lebih umum untuk mengatasinya:

1
2
	var defaults:Object = {
3
		laserColor:red,
4
		personality: "evil"
5
	}
6
	
7
	for (var key:String in defaults){
8
		if (!conf[key]) {
9
			conf[key] = defaults[key];
10
		}
11
	}

Perulangan for itu mungkin sedikit membingungkan, jadi saya akan memecahnya. Pertama, lihat ini:

1
2
	for (var key:String in defaults){
3
		trace(key);
4
	}

Ini adalah perulangan for...in, yang akan menampilkan nama-nama kunci di dalam obyek default:

1
2
laserColor
3
personality

Selanjutnya, lihat baris ini:

1
2
trace(defaults["laserColor"]);

Ini akan menghasilkan red - sama dengan menulis trace(defaults.laserColor).

Setelah itu, lihat contoh ini:

1
2
var example:Object = { demo: "test" };
3
trace(example["demo"]);
4
trace(example["foo"]);

Menurut Anda apa yang akan dihasilkan ini?

Nah, example["demo"] sama dengan example.demo, yang sama dengan "test". Tapi example.foo tidak ada, jadi example["foo"] akan mengembalikan null. Ini berarti bahwa !example["foo"] (perhatikan tanda seru) akan sama dengan true.

Gabungkan semuanya, dan Anda harus dapat memahami mengapa kode ini bekerja:

1
2
	var defaults:Object = {
3
		laserColor:red,
4
		personality: "evil"
5
	}
6
	
7
	for (var key:String in defaults){
8
		if (!conf[key]) {
9
			conf[key] = defaults[key];
10
		}
11
	}

Beri saya teriakan di komentar jika Anda butuh bantuan!

Saya ingin lebih!

Untuk versi yang lebih cepat, coba ini:

1
2
function generateRobot(conf:Object = null):Robot {
3
	var conf:Object = conf || {};
4
	var defaults:Object = {
5
		laserColor:red,
6
		personality: "evil"
7
	}
8
	
9
	for (var key:String in defaults){
10
		conf[key] = conf[key] || defaults[key];
11
	}

Perubahan pada Baris 1 (dan Baris 2 yang baru) berarti bahwa bahkan obyek conf itu sendiri adalah opsional, jadi Anda bisa memanggil generateRobot(). (Tentu saja, Anda harus mengubah kode untuk menangani nilai-nilai yang saat ini tidak memiliki default.)


Membantu IDE agar Membantu Anda

Seperti yang saya sebutkan di atas, IDE tidak dapat memberi Anda tips tentang parameter apa yang diharapkan oleh fungsi, jika fungsi itu menggunakan obyek konfigurasi. Ini adalah kelemahan utama, karena dapat membuat kode Anda sangat sulit digunakan; Anda harus mengingat parameter mana yang masuk dalam obyek conf, serta semua nama dan tipe mereka.

Tetapi kita masih bisa menampilkan informasi ini ke pembuat kode ketika dibutuhkan; kita hanya perlu melakukannya secara manual, seperti:

1
2
			/**

3
			 * Generate a robot, based on the parameters given.

4
			 * @param	conf	Configuration object. Expects:

5
				 * arms 		(int)		Number of arms robot should have.

6
				 * personality 	(String)	Personality of robot. Can be "evil" or "good". Defaults to "evil".

7
				 * material		(String)	What the robot should be made out of. Can be "steel" or "wood" at this time.

8
				 * laserColor	(String)	Color of the robot's laser. Defaults to "red".

9
				 * voice		(String)	Vocal stylings of robot. Currently not implemented.

10
			 * @return	The finished robot.

11
			 */
12
			function generateRobot(conf:Object):Robot {
13
				//

14
			}

Sekarang, jika saya mulai menulis panggilan ke fungsi ini di FlashDevelop (IDE pilihan saya), saya melihat ini:

Tentu, ini agak menyebalkan untuk tetap memperbarui ini secara manual, tetapi dalam banyak kasus itu sepadan.


Kesimpulan

Saya tidak mengklaim bahwa Anda harus menggunakan obyek konfigurasi untuk setiap fungsi tunggal yang Anda buat mulai sekarang; anggap saja itu sebagai alat lain yang berguna dalam gudang senjata Anda.

Secara pribadi, saya menemukan pola yang sangat berguna setiap kali saya membangun konsep pertama dari beberapa kelas yang semua harus bekerja bersama. Fleksibilitas tambahan dari sebuah conf memberikan saya jauh lebih banyak fleksibilitas, membebaskan saya untuk menangani semua fungsi yang berbeda dan mengubah cara mereka memanggil satu sama lain, tanpa khawatir tentang memecahkan kode dengan memasukkan atau menghapus parameter.

Ingat manfaatnya:

  • Sangat mudah untuk menambah dan menghapus parameter (di kedua ujungnya).
  • Mudah untuk menetapkan nilai default.
  • Anda tidak perlu khawatir tentang urutan parameter.

Ada beberapa kelemahan dalam menggunakan obyek sederhana seperti yang saya miliki - terutama jika Anda melakukannya dalam proyek yang melewati tahap prototyping. Lihat komentar-komentar hebat di bawah ini untuk lebih jelasnya!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.