Cara Mendekati Pengembangan WordPress Modern (Bagian 2)

Diterbitkan: 2022-03-11

WordPress adalah teknologi situs yang paling banyak digunakan di planet ini dan dengan alasan yang bagus. Namun kode warisan pada intinya berantakan, dan masalah ini mengalir ke pengembang pihak ketiga. Beberapa pengembang menganggap ini sebagai alasan untuk mengambil jalan pintas dalam kode PHP WordPress mereka sendiri, tetapi pendekatan ini lebih mahal dalam jangka panjang untuk semua kecuali perubahan yang paling sepele.

Di Bagian 1 dari seri dua bagian kami, kami berfokus pada alat proyek dan alur kerja secara keseluruhan, diikuti oleh pengembangan front-end. Sekarang saatnya untuk mengambil banteng dengan tanduknya, dan bergulat dengan PHP: Secara khusus, bagaimana mengikuti praktik terbaik saat bekerja dengan kode WordPress back-end. Anda mungkin menganggap ini sebagai tutorial PHP/WordPress, tetapi sedikit lebih maju, dengan asumsi bahwa Anda telah melakukan beberapa kustomisasi back-end WordPress.

Jadi, prinsip desain perangkat lunak modern dan fitur PHP mana yang akan memberi Anda nilai terbaik untuk waktu Anda? Berikut ini adalah 10 praktik pengembangan WordPress dan PHP yang sangat saya rekomendasikan.

Praktik Terbaik Pengembangan WordPress Modern #1: Ikuti “Pemisahan Kekhawatiran”

Pemisahan masalah berarti bahwa bagian dari kode PHP WordPress yang memiliki fungsi atau tujuan yang berbeda tidak boleh dicampur bersama. Sebaliknya, mereka harus diatur ke dalam bagian atau modul yang berbeda, meneruskan data satu sama lain melalui antarmuka yang ditentukan. ( Antarmuka adalah seperangkat parameter yang ditentukan yang diambil modul sebagai input, dan apa yang dihasilkan kembali.) Istilah yang terkait erat adalah prinsip tanggung jawab tunggal : Setiap modul kode (atau fungsi) harus bertanggung jawab untuk satu hal saja.

Tujuan akhir dari mengikuti prinsip-prinsip ini adalah menghasilkan kode yang modular, dan dengan demikian dapat dipelihara, dapat diperluas, dan dapat digunakan kembali.

Itu cukup banyak, jadi mari kita lihat contoh beberapa WordPress PHP (dari inti WordPress) yang membuat semuanya kusut. Gaya pengkodean ini sering disebut "kode spageti" karena memahami cara kerja bagian dalamnya hampir tidak mungkin. Kutipan di bawah ini telah disunting untuk singkatnya; namun, gaya dan format aslinya tetap dipertahankan.

 $id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0; <table class="form-table"> <?php $blog_prefix = $wpdb->get_blog_prefix( $id ); $sql = "SELECT * FROM {$blog_prefix}options WHERE option_name NOT LIKE %s AND option_name NOT LIKE %s"; $query = $wpdb->prepare( $sql, $wpdb->esc_like( '_' ) . '%', '%' . $wpdb->esc_like( 'user_roles' ) ); $options = $wpdb->get_results( $query ); foreach ( $options as $option ) { if ( strpos( $option->option_value, "\n" ) === false ) { ?> <tr class="form-field"> <th scope="row"><label for="<?php echo esc_attr( $option->option_name ); ?>"><?php echo esc_html( ucwords( str_replace( '_', ' ', $option->option_name ) ) ); ?></label></th> <?php if ( $is_main_site && in_array( $option->option_name, array( 'siteurl', 'home' ) ) ) { ?> <td><code><?php echo esc_html( $option->option_value ); ?></code></td> <?php } else { ?> <td><input class="<?php echo $class; ?>" name="option[<?php echo esc_attr( $option->option_name ); ?>]" type="text" value="<?php echo esc_attr( $option->option_value ); ?>" size="40" <?php disabled( $disabled ); ?> /></td> <?php } ?> </tr> <?php } } // End foreach </table>

Pertama-tama, itu benar-benar tidak bisa dipahami. Dan saya suka bahwa satu-satunya komentar adalah End foreach , yang benar-benar berlebihan. Kami memiliki kueri basis data, pemrosesan hasil kueri, pemrosesan tambahan yang disematkan dalam HTML (ada if / else bersarang di sana jika Anda tidak menyadarinya), pelolosan keluaran, dan templating HTML semuanya disatukan. Masalah lain adalah parameter $id yang datang langsung dari global $_REQUEST sebagai lawan dari melewatkan parameter aktual ke suatu fungsi.

Melihat ini, sangat dapat dimengerti mengapa inti WordPress sebagian besar tetap sama selama bertahun-tahun. Memfaktorkan ulang kode semacam ini — terutama sambil mempertahankan perilaku yang ada — adalah tugas yang benar-benar epik yang tidak ingin dilakukan oleh siapa pun.

Jadi bagaimana kita melakukannya dengan benar? Nah, satu hal yang perlu diingat adalah bahwa tidak ada satu cara yang benar . Kami menyebutkan kualitas di atas yang harus kami perjuangkan: Kami membutuhkan kode PHP kustom WordPress agar dapat dipelihara dan modular. Mari kita lihat bagaimana kita dapat membagi kode di atas menjadi beberapa modul.

  • Kueri SQL harus dalam modul terpisah, tentu saja. WordPress sudah memiliki kelas WP_Query yang diabstraksi dengan baik yang harus digunakan sebagai contoh.
  • Semua HTML masuk ke dalam template. Kami akan membahas template PHP lebih lanjut di bawah ini.
  • Kode PHP yang tersisa harus dibungkus dalam suatu fungsi—beberapa fungsi jika kodenya terlalu panjang atau rumit untuk satu fungsi. Parameter seperti $id dilewatkan melalui argumen fungsi.

Ini adalah penulisan ulang yang sangat disederhanakan dari contoh di atas:

 function betterSiteSettings($args) { $data = WP_Settings_Query($args); // process $data here $context = array_merge([], $data_processed, $other_data); return Template::render('template.name', $context); }

Praktik Terbaik Pengembangan WordPress Modern #2: Hindari Variabel Global

WordPress memiliki terlalu banyak variabel global. Mengapa variabel global buruk? Mereka membuat kode PHP WordPress Anda sulit untuk diikuti dan membuat status aplikasi tidak dapat diandalkan. Setiap bagian dari kode PHP—dan itu berarti plugin apa pun yang diinstal di WordPress—dapat membaca dan menulis variabel global, jadi tidak ada jaminan bahwa variabel tersebut berisi data yang valid. Mencoba memahami variabel global apa yang digunakan dalam sesuatu seperti Loop juga bukan tugas yang sepele.

Mari kita lihat ini dari sudut praktis. Contoh ini berasal dari WooCommerce. Mungkin setiap pengembang WordPress tahu apa itu—Loop:

 <?php while ( have_posts() ) : the_post(); ?> <?php wc_get_template_part( 'content', 'single-product' ); ?> <?php endwhile; // end of the loop. ?>

Cuplikan di atas merender template produk. Bagaimana cara mengetahui produk apa yang akan ditampilkan, mengingat tidak ada parameter yang diteruskan ke wc_get_template_part ? Melihat template, kita melihat bahwa itu dimulai dengan global $product; , jadi di situlah objek produk saat ini disimpan.

Sekarang bayangkan kita memiliki halaman katalog yang mencari dan memfilter produk, dan kita ingin menampilkan popup “detail produk” sambil tetap berada di halaman yang sama. Di belakang layar, skrip front-end melakukan permintaan AJAX untuk mendapatkan template produk tertentu. Kita tidak bisa begitu saja memanggil wc_get_template_part('content', 'single-product') karena tidak menggunakan parameter, jadi kita perlu menyetel beberapa variabel global agar ini berfungsi.

Kasus penggunaan yang lebih kompleks akan melibatkan lebih dari satu templat, kait yang dipicu di templat tersebut, dan plugin pihak ketiga menambahkan panggilan balik mereka ke kait tersebut. Itu bisa meningkat dengan cepat. Kami tidak memiliki cara untuk mengetahui keadaan global yang diandalkan oleh panggilan balik tersebut. Plugin pihak ketiga bebas memodifikasi variabel global apa pun dalam panggilan baliknya. Alih-alih menggunakan sistem, kami mulai berkelahi dengan sistem, menemukan bug aneh yang berasal dari keadaan global yang tidak dapat diandalkan.

Bukankah lebih masuk akal untuk meneruskan ID produk itu sebagai parameter? Kemudian kita dapat menggunakan kembali template itu tanpa khawatir akan mengacaukan variabel global yang digunakan oleh WordPress.

Praktik Terbaik Pengembangan WordPress Modern #3: Gunakan Pemrograman Berorientasi Objek (OOP)

Modularitas mengarah pada konsep objek dan pemrograman berorientasi objek. Pada tingkat yang paling dasar, OOP adalah cara mengatur kode. Fungsi dan variabel digabungkan bersama ke dalam kelas dan masing-masing disebut metode dan properti kelas. Buku Pegangan Plugin WordPress merekomendasikan penggunaan OOP untuk mengatur kode PHP kustom WordPress Anda.

Prinsip penting dalam OOP adalah membatasi akses ke metode dan properti—atau dalam istilah PHP, menyatakannya sebagai private atau protected —jadi hanya metode kelas lain yang dapat mengakses dan mengubahnya. Istilah OOP untuk ini adalah enkapsulasi : Data dienkapsulasi di dalam kelas, dan satu-satunya cara untuk mengubah data itu adalah dengan menggunakan metode kelas yang disediakan.

Ini membuat proses debug dan pemeliharaan kode Anda jauh lebih mudah daripada saat menggunakan variabel global yang dapat dimodifikasi di mana saja di seluruh basis kode. Pertimbangkan variabel post WordPress global. Anda dapat mengaksesnya di mana saja dalam kode Anda, dan banyak fungsi bergantung pada penggunaannya. Bagaimana jika Anda dapat membatasi modifikasi hanya pada fungsi inti WordPress, tetapi membaca akan diizinkan untuk siapa saja? Menyembunyikan atau merangkum variabel post global di kelas dan membangun antarmuka di sekitarnya akan memungkinkan hal ini.

Ini hanya deskripsi dasar OOP dan bagaimana OOP dapat digunakan dalam pengembangan WordPress modern. Untuk studi lebih lanjut, saya sangat merekomendasikan e-book Carl Alexander, Temukan pemrograman berorientasi objek menggunakan WordPress, yang memiliki konten paling komprehensif dan berguna yang tersedia tentang topik OOP di WordPress.

Penting untuk diingat bahwa OOP bukanlah peluru perak: Kode buruk dapat ditulis dengan OOP semudah dengan paradigma pemrograman lainnya.


Mari selami beberapa saran khusus tentang penggunaan PHP untuk pengembangan WordPress.

Praktik Terbaik PHP Modern #1: Targetkan PHP 7.0+

Menggunakan fitur PHP modern membutuhkan versi PHP yang modern. Tidak ada alasan untuk mendukung versi PHP yang lebih rendah dari 7.0. Bahkan inti WordPress akan membutuhkan PHP 7.0 pada akhir 2019.

Namun demikian, ini adalah praktik yang baik untuk memeriksa versi minimum Anda untuk menghindari "layar putih kematian" di lingkungan yang tidak kompatibel. Cuplikan di bawah ini menunjukkan penggunaan header plugin untuk mendeklarasikan versi PHP minimum dengan kondisi penjaga dalam kode.

 <?php /** * Plugin Name: My Awesome Plugin * Requires PHP: 7.0 */ // bails if PHP version is lower than required if (version_compare(PHP_VERSION, '7.0.0', '<')) { // add admin notice here return; } // the rest of the actual plugin here

Praktik Terbaik PHP Modern #2: Mengadopsi Standar Industri PHP (Panduan Gaya Pengkodean PSR-2)

PSR adalah rekomendasi yang diterbitkan oleh PHP Framework Interop Group. Mereka adalah standar industri de-facto dalam alur kerja PHP modern apa pun, dan dapat dikatakan dengan aman bahwa komunitas PHP secara keseluruhan mengikuti standar ini. PSR-2 adalah rekomendasi yang menggambarkan gaya pengkodean. Kerangka kerja PHP populer seperti Symfony dan Laravel mengikuti PSR-2.

Mengapa Anda menggunakan PSR-2 alih-alih standar pengkodean WordPress? Terutama karena standar WordPress sudah usang dan tidak menggunakan fitur bahasa yang lebih baru. Itu bisa dimengerti karena inti WordPress harus mengikuti standarnya sendiri. Itu harus mendukung PHP 5.2 sampai baru-baru ini, dan PSR-2 tidak kompatibel dengan PHP 5.2.

Ini mungkin tidak jelas, tetapi tidak ada persyaratan untuk menggunakan standar pengkodean WordPress kecuali Anda berkomitmen pada intinya. Tidak akan ada masalah dengan mengirimkan plugin yang mengikuti standar PSR-2 ke direktori plugin WordPress. Sebenarnya, ada beberapa argumen yang sangat bagus untuk melakukannya.

Praktik Terbaik PHP Modern #3: Gunakan Mesin Template PHP

PHP bukan mesin template. Ini dimulai sebagai satu, tetapi kemudian berkembang menjadi bahasa pemrograman berfitur lengkap, dan tidak ada alasan untuk tetap menggunakannya untuk templating. Dua mesin template paling populer untuk PHP adalah Twig dan Blade, yang masing-masing digunakan oleh Symfony dan Laravel. Artikel ini akan menggunakan Twig sebagai contoh mesin templating; namun, Blade memiliki fitur dan fungsionalitas yang sebanding. Saya mohon Anda untuk melihat keduanya dan memutuskan sendiri mana yang paling cocok untuk Anda.

Contoh di bawah ini membandingkan template PHP dan template Twig yang sesuai. Menampilkan dan keluar dari output sangat bertele-tele dalam contoh PHP:

 foreach ( $options as $option ) { ?> <tr class="form-field"> <th scope="row"> <label for="<?php echo esc_attr( $option->option_name ); ?>"> <?php echo esc_html( strtolower( $option->option_name ) ); ?> </label> </th> </tr> <?php } // End foreach

Di Twig, ini lebih ringkas dan mudah dibaca:

 {% for option in options %} <tr class="form-field"> <th scope="row"> <label for="{{ option.option_name }}"> {{ option.option_name }} </label> </th> </tr> {% endfor %}

Keuntungan utama Twig adalah:

  • Sintaks yang mudah dibaca dan ringkas
  • Keluaran otomatis keluar
  • Ekstensi template melalui pewarisan dan blok

Dari segi kinerja, Twig mengkompilasi ke template PHP dan hampir tidak memiliki overhead. Twig hanya memiliki subset dari konstruksi bahasa PHP yang terbatas pada pembuatan template saja. Ini memaksa pengembang untuk menghapus logika bisnis dari template, sehingga memberlakukan pemisahan kekhawatiran.

Bahkan ada Twig untuk WordPress. Ini disebut Timber, dan ini adalah cara yang bagus untuk memulai membuat template yang lebih baik. Tema pemula Timber adalah contoh sempurna untuk mengatur tema dengan cara OOP.

Praktik Terbaik PHP Modern #4: Gunakan Komposer

Komposer adalah manajer ketergantungan untuk PHP. Ini adalah alat yang memungkinkan untuk mendeklarasikan pustaka yang digunakan proyek, dan kemudian mengotomatiskan unduhan, penginstalan, dan pembaruannya. Maka Anda hanya perlu menyertakan file autoload Composer vendor/autoload.php alih-alih secara manual membutuhkan setiap perpustakaan.

Plugin dan tema WordPress tidak sering menggunakan perpustakaan pihak ketiga. Ini sebagian karena WordPress memiliki API ekstensif yang memenuhi hampir semua kebutuhan, dan sebagian lagi karena kemungkinan konflik versi. Pertimbangkan dua plugin yang membutuhkan pustaka PHP yang sama tetapi versinya berbeda. Plugin yang berjalan pertama mendapatkan versi yang benar dan plugin kedua mendapatkan versi itu juga. Ini sangat mungkin situasi layar putih kematian lainnya.

Untuk menghindari konflik, manajemen ketergantungan harus digunakan di tingkat aplikasi, yaitu situs WordPress secara keseluruhan. Inilah yang dilakukan Roots (Bedrock, lebih khusus). Saat digunakan pada tingkat paket (plugin atau tema), Komposer dapat menyebabkan konflik saat menggunakan pustaka pihak ketiga. Ini masalah yang diketahui. Satu-satunya solusi yang ada sejauh ini adalah mengganti nama ruang nama perpustakaan eksternal itu menjadi sesuatu yang unik, dan itu bukan tugas yang sepele.

Masih ada kegunaan untuk Komposer: pemuatan otomatis kelas Anda sendiri. Tapi sebelum kita melangkah lebih jauh dengan autoloading, kita perlu mempercepat dengan PHP namespaces.

Praktik Terbaik PHP Modern #5: Gunakan Namespaces

Inti WordPress menjadi proyek warisan, ia menggunakan namespace global atau, dengan kata lain, tidak ada namespace sama sekali. Setiap kelas atau fungsi yang dideklarasikan secara global (artinya tidak di dalam kelas atau fungsi lain) terlihat di mana saja di seluruh basis kode. Nama mereka harus unik tidak hanya dalam basis kode Anda tetapi untuk semua plugin dan tema yang digunakan sekarang atau mungkin akan digunakan di masa mendatang.

Tabrakan penamaan (misalnya, mendeklarasikan fungsi dengan nama yang sudah ada) biasanya mengarah ke layar putih kematian, dan kami tidak menginginkannya. Codex WordPress menyarankan untuk mengawali semua fungsi dan kelas Anda dengan sesuatu yang unik. Jadi, alih-alih memiliki nama kelas sederhana seperti Order , kita mendapatkan sesuatu seperti Akrte_Awesome_Plugin_Order di mana "Akrte" adalah awalan unik yang baru saja saya buat.

Ruang nama dapat dilihat sebagai grup—atau folder, jika kita menggunakan analogi sistem file—yang membantu mengatur kode dan menghindari tabrakan nama. Anda dapat memiliki ruang nama kompleks yang dipisahkan dengan garis miring, seperti folder bersarang. (Ruang nama PHP menggunakan garis miring terbalik pada khususnya.)

Bagian namespace itu disebut sub-namespaces. Kelas contoh kami Akrte_Awesome_Plugin_Order akan menjadi Akrte\Awesome_Plugin\Order jika dilakukan menggunakan ruang nama. Di sini Akrte dan Awesome_Plugin adalah bagian namespace (atau sub-namespaces) dan Order adalah nama kelas. Kemudian Anda dapat menambahkan pernyataan use dan hanya menggunakan nama kelas sesudahnya. Itu pasti terlihat lebih baik:

 use Akrte\Awesome_Plugin\Order; $a = new Order;

Jelas, ruang nama harus unik; dengan demikian, kita harus memberikan sub-namespace "root" pertama nama yang unik, dan itu biasanya nama vendor. Sebagai contoh, kelas WC_REST_Order_Notes_V2_Controller dapat dilakukan ulang dengan ruang nama seperti ini:

 namespace WooCommerce\RestApi\V2\Controllers; class OrderNotes {}

Basis kode WooCommerce saat ini menggunakan ruang nama; misalnya, di WooCommerce REST API versi 4.

Praktik Terbaik PHP Modern #6: Gunakan Pemuat Otomatis

Di sebagian besar alur kerja PHP, cara biasa untuk menautkan file PHP adalah dengan menggunakan pernyataan require atau include . Saat proyek berkembang, Anda mendapatkan lusinan pernyataan yang require di file plugin utama Anda. Sebuah autoloader mengotomatisasi termasuk file dan melakukannya hanya jika diperlukan. Secara teknis ini adalah fungsi yang require file sa yang berisi kelas atau fungsi saat pertama kali ditemukan dalam kode. Tidak perlu lagi menambahkan pernyataan yang require secara manual.

Seringkali ada juga peningkatan kinerja yang signifikan karena autoloader hanya memuat modul yang digunakan dalam permintaan tertentu. Tanpa autoloader, seluruh basis kode Anda disertakan bahkan jika permintaan hanya menggunakan, katakanlah, 10 persen dari kode Anda.

Fungsi autoloader perlu mengetahui file mana yang digunakan kelas dan fungsi Anda. Dan ada standar PHP-FIG, PSR-4, untuk itu.

Dikatakan bahwa bagian dari namespace, awalan, ditunjuk untuk berhubungan dengan folder dasar. Sub-ruang nama yang mengikutinya sesuai dengan folder di dalam folder dasar. Akhirnya, nama kelas sesuai dengan nama file. Contoh kelas Akrte\AwesomePlugin\Models\Order akan membutuhkan struktur folder di bawah ini:

 /awesome-plugin awesome-plugin.php /includes /Models Order.php

Awalan namespace Akrte\AwesomePlugin\ sesuai dengan folder includes sebagaimana ditentukan dalam konfigurasi autoloader yang dibahas di bawah ini. Sub-namespace Models Models sesuai, dan kelas Order terdapat di Order.php .

Untungnya, Anda tidak perlu mengimplementasikan fungsi autoloader sendiri. Komposer dapat membuat autoloader untuk Anda:

  1. Instal Komposer
  2. Buat file composer.json di folder root proyek Anda. Itu harus berisi baris-baris ini:
 { "name": "vendor-name/plugin-name", "require": {}, "autoload": { "psr-4": { "Akrte\\AwesomePlugin\\": "includes/" } } }
  1. Jalankan composer install .
  2. Sertakan vendor/autoload.php di bagian atas file PHP plugin utama Anda seperti ini:
 <?php /** * Plugin Name: My Awesome Plugin */ defined('ABSPATH') || exit; require __DIR__ . '/vendor/autoload.php'; // do stuff

Selain namespace, basis kode terbaru WooCommerce juga menggunakan autoloader Composer.


Dengan membahas prinsip-prinsip desain PHP ini, inilah saatnya untuk mengikat semua pelajaran PHP kami kembali ke kustomisasi back-end WordPress dengan satu rekomendasi terakhir.

Praktik Terbaik Pengembangan WordPress Modern #4: Pertimbangkan Menggunakan Roots Stack

Roots adalah alur kerja pengembangan WordPress modern terlengkap yang pernah ada. Namun, saya akan mengatakan bahwa itu tidak harus digunakan di setiap proyek WordPress, karena:

  • Root harus digunakan dari awal. Alasan paling umum, memang. Memfaktorkan ulang proyek yang ada akan terlalu mahal.
  • Ini berpendirian. Baik ketika Anda setuju, buruk ketika Anda tidak setuju. Anda mungkin lebih suka cara lain untuk mengatur tema Anda, misalnya. Proyek beropini juga membutuhkan waktu untuk mempelajari “cara mereka”.
  • Tidak semua orang mengetahuinya. Pengembang yang akan datang setelah Anda untuk memelihara situs yang Anda buat dengan tumpukan Roots mungkin tidak tahu apa itu dan bertanya-tanya apa yang terjadi dengan folder WordPress. Kita harus memikirkan sesama pengembang WordPress.

Secara umum, Anda ingin memahami sepenuhnya semua keuntungan dan kerugian dari setiap proyek yang sangat keras pendapatnya sebelum berkomitmen untuk menggunakannya.

Prinsip PHP dan Perangkat Lunak Modern: Membuat Pengembangan Back-end WordPress Kuat

Cukup jelas bahwa tidak ada satu cara yang benar untuk menulis perangkat lunak. Konsep-konsepnya, seperti pemisahan kekhawatiran, sudah berumur puluhan tahun; Namun, apa artinya praktis selalu diperebutkan. Ambil, misalnya, CSS. Pada awalnya, kami menggariskannya sebagai style dalam HTML, lalu kami memutuskan bahwa lembar CSS terpisah adalah tentang pemisahan kekhawatiran.

Maju cepat satu dekade: Aplikasi JavaScript masa kini menggunakan komponen sebagai implementasi pemisahan masalah. Pengembang front-end condong ke CSS-in-JS, dan itu pada dasarnya berarti menyejajarkan CSS dalam HTML lagi (yah, itu tidak sesederhana itu, tetapi Anda mendapatkan idenya). Lingkaran selesai!

Praktik terbaik selalu tentang meningkatkan pengalaman pengembang:

Program harus ditulis untuk dibaca orang, dan hanya secara kebetulan untuk dieksekusi oleh mesin.

Abelson & Sussman, Struktur dan Interpretasi Program Komputer

Beberapa praktik dalam tutorial PHP WordPress ini cepat dan mudah diterapkan di proyek Anda. Misalnya, autoloader: Lakukan satu kali per proyek, dan nikmati saja. Di sisi lain, ide arsitektur perangkat lunak baru membutuhkan waktu, latihan, dan banyak iterasi agar praktis dan nyaman. Padahal, imbalannya jauh lebih besar. Anda tidak hanya akan lebih efisien pada apa yang Anda lakukan tetapi juga menikmati apa yang Anda lakukan lebih banyak. Dan kenikmatan rutin dari pekerjaan yang Anda lakukan untuk klien mungkin merupakan satu-satunya cara agar pekerjaan tersebut dapat berkelanjutan.