Cara membuat Pemeriksa Kode mencintai Anda





Dalam hal inspeksi kode, perhatian orang biasanya terfokus pada siapa yang melakukannya. Tetapi pengembang yang menulis kode memainkan peran yang sama pentingnya dalam proses seperti pengulas. Hampir tidak ada rekomendasi untuk menyiapkan kode untuk diperiksa, jadi penulis sering membuat kesalahan hanya karena ketidaktahuan.



Artikel ini mengumpulkan praktik terbaik untuk berpartisipasi dalam pemeriksaan kode sebagai penulis. Ketika Anda selesai membaca, Anda akan mulai mengirimkan kepada pengawas serangkaian perubahan yang sempurna sehingga mereka akan membakar dengan cinta untuk Anda, tidak kurang.



Tapi saya tidak ingin pemeriksa kode bersinar dengan cinta untuk saya



Dan mereka akan tetap ada. Rendahkan dirimu. Tidak ada seorang pun dalam sejarah umat manusia yang mengeluh di ranjang kematiannya bahwa dia terlalu dicintai selama hidupnya.



Mengapa meningkatkan pemeriksaan kode?



Mempelajari teknik inspeksi yang efektif akan membuat hidup lebih mudah bagi inspektur, tim, dan yang terpenting, Anda.



  • Proses transfer pengetahuan yang dipercepat. Jika Anda mempersiapkan rangkaian perubahan dengan benar, perhatian pengawas akan diarahkan ke area yang Anda butuhkan untuk berkembang, daripada kekurangan gaya yang membosankan. Dan ketika Anda menjelaskan bahwa Anda menghargai kritik yang membangun, pengkaji mulai berusaha lebih keras untuk memberikan umpan balik.
  • Teladan bagi orang lain. Praktik pemeriksaan kode yang baik dalam eksekusi Anda akan menentukan standar bagi orang-orang di sekitar Anda. Teknik yang baik biasanya diterapkan, yang berarti akan lebih mudah bagi Anda ketika seseorang dari kolega Anda mengirimi Anda kode untuk ditinjau.
  • Konflik minimum. Pemeriksaan kode sering kali menimbulkan ketegangan dalam tim. Jika Anda menangani masalah secara bertanggung jawab dan sadar, perselisihan akan lebih jarang muncul.


Aturan emas: hargai waktu pengulas



Ini tampaknya jelas, tetapi saya sering menjumpai penulis yang memperlakukan inspektur sebagai spesialis kontrol kualitas pribadi mereka. Orang-orang seperti itu tidak akan berusaha untuk menangkap setidaknya beberapa kesalahan atau membuat serangkaian perubahan nyaman untuk diperiksa.



Kolega Anda bekerja setiap hari dengan persediaan perhatian yang terbatas. Jika mereka mencurahkan sebagian untuk Anda, maka mereka tidak dapat lagi menggunakan sumber daya ini untuk tugas mereka sendiri. Memanfaatkan waktu mereka sebaik-baiknya adalah masalah keadilan sederhana.



Peninjauan kode akan jauh lebih berhasil jika para peserta dapat saling percaya. Inspektur Anda akan berusaha sekuat tenaga jika dia tahu bahwa Anda akan menanggapi ucapannya dengan serius. Jika Anda menganggap penguji sebagai hambatan yang perlu diatasi, maka Anda akan menerima rekomendasi yang jauh lebih tidak berharga darinya.



Teknik



1. Tinjau kode sendiri



terlebih dahulu Sebelum mengirim kode ke rekan kerja, bacalah. Jangan membatasi diri Anda untuk menangkap kesalahan - bayangkan melihat fragmen ini untuk pertama kalinya. Apa yang bisa membingungkan tentang itu?



Menurut pengalaman saya, ada baiknya untuk mengambil jeda antara menulis dan mengedit kode. Orang sering mengirim kode baru di penghujung hari, tetapi selama periode inilah mereka kemungkinan besar akan melewatkan sesuatu karena kelalaian. Tunggu hingga pagi, lihat sekilas kumpulan perubahan, lalu bagikan kepada rekan kerja.







Orang bodoh apa yang menulis itu?

Menyinkronkan Cron Jobs dengan siklus lunar: Saya menambahkan logika tersinkronisasi untuk menjaga




pipeline ETL kita selaras dengan alam. Simulasikan lingkungan kerja validator sebanyak mungkin. Gunakan utilitas perbandingan yang sama seperti yang dia lakukan. Bug bodoh ditemukan lebih baik di utilitas ini daripada di editor kode biasa Anda.



Jangan berharap diri Anda sempurna. Anda pasti akan mengirim kode dengan bagian yang Anda lupa hapus setelah memperbaiki bug, atau file tersesat yang akan Anda hapus. Ini bukan akhir dunia, tetapi hal-hal seperti ini patut diperhatikan. Perhatikan pola kesalahan Anda dan cari tahu sistem apa yang dapat Anda terapkan untuk mencegahnya. Jika kesalahan yang sama sangat sering terjadi, inspektur akan menyimpulkan bahwa Anda tidak menghargai waktunya.



2. Tulis deskripsi yang jelas tentang set perubahan



Dalam pekerjaan mentoring saya yang terakhir, saya sesekali bertemu dengan programmer yang lebih berpengalaman. Sebelum pertemuan pertama, dia meminta saya untuk mengambil dokumen desain perangkat lunak yang telah saya susun. Saat saya menyerahkan kertas-kertas itu, saya menjelaskan apa proyek itu dan bagaimana hubungannya dengan tujuan tim saya. Mentor saya mengerutkan kening dan berkata terus terang, "Semua yang baru saja Anda katakan harus ada di halaman pertama dokumen."



Dan dia benar. Saya menulis dokumen dengan harapan pengembang dari tim saya, tetapi tidak memperhitungkan bahwa mungkin dibaca oleh orang luar juga. Penonton tidak terbatas pada batasan departemen saya - masih ada tim mitra, mentor, orang yang membuat keputusan tentang promosi... Dokumen itu harus ditulis sedemikian rupa sehingga semuanya jelas bagi mereka. Setelah percakapan ini, saya selalu mencoba mempresentasikan karya saya dalam konteks yang diperlukan untuk pemahaman.



Deskripsi perubahan harus mencakup informasi latar belakang yang mungkin dibutuhkan pembaca. Meskipun Anda menulis deskripsi untuk menargetkan pengulas, perlu diingat bahwa informasi kontekstualnya mungkin kurang dari yang Anda kira. Selain itu, kolega lain mungkin juga harus bekerja dengan kode ini di masa mendatang - saat melihat riwayat perubahan, mereka harus memahami maksud Anda.



Penjelasan yang baik menguraikan untuk apa set perubahan itu dan mengapa Anda memilih melakukannya dengan cara itu.



Jika Anda ingin mendalami seni menulis deskripsi yang bagus lebih dalam, baca " Bagaimana Menulis Pesan Komitmen Git " oleh Chris Beams dan " Komitmen Git favorit saya " oleh David Thompson.



3. Mengotomatiskan Hal-Hal Sederhana



Jika Anda mengandalkan inspektur untuk hal-hal kecil seperti penjepit keriting mengambang atau masalah dengan pengujian otomatis, Anda akan membuang-buang waktunya.







Periksa apakah semuanya sesuai dengan sintaks? Saya akan beralih ke kompiler, tapi sayang membuang-buang waktunya.



Tes otomatis harus dianggap sebagai bagian dari prosedur standar sebagai bagian dari tim. Inspeksi dimulai hanya jika seluruh rangkaian pemeriksaan otomatis dalam lingkungan integrasi berkelanjutan telah berlalu .



Jika tim Anda mengalami delusi yang tragis dan menolak integrasi berkelanjutan, siapkan pembayaran otomatis di rumah. Menerapkan hook , linter, dan pemformat pra-komitmen ke dalam lingkungan pengembangan Anda untuk memastikan bahwa semua konvensi diikuti dan perilaku yang diinginkan tetap ada dari komitmen hingga komitmen.



4. Pastikan kode itu sendiri menjawab pertanyaan



Ada apa dengan gambar ini?







Saya tidak mengerti tujuan dari fungsinya.

Dan, dalam hal ini Frombobulator diteruskan ketika memanggil tanpa adanya implementasi frombobulate.




Penulis membantu saya mengetahui fungsinya, tetapi bagaimana dengan pembaca berikutnya? Menggali sejarah perubahan dan membaca kembali semua diskusi? Lebih buruk lagi ketika penulis datang ke meja saya untuk menjelaskan semuanya secara langsung. Pertama, hal itu menghalangi saya untuk berkonsentrasi, dan kedua, tidak ada jiwa yang hidup yang memiliki akses ke informasi yang bersuara lagi.



Ketika seorang inspektur mengungkapkan kebingungan tentang suatu poin dalam kode, tugas Anda bukanlah mengklarifikasi situasi orang itu. Penting untuk memperjelas situasi untuk semua orang sekaligus.







- Halo?

- Ketika Anda menulis bill.py enam tahun lalu, mengapa Anda memiliki t = 6?

- Senang kamu menelepon! Ini karena pajak penjualan 6%.

- Tentu saja!

- Cara yang bagus untuk membenarkan keputusan implementasi.




Jawaban terbaik untuk pertanyaan apa pun adalah pemfaktoran ulang kode yang menghapusnya. Apa yang bisa diganti namanya agar lebih jelas bagaimana mengubah logika? Komentar adalah solusi yang dapat diterima, tetapi mereka pasti kalah dengan latar belakang kode yang secara alami mendokumentasikan dirinya sendiri.



5. Masukkan perubahan sedikit demi sedikit



Batasan yang luas adalah praktik yang buruk dan sering kali terlihat saat memeriksa kode. Pengembang berupaya untuk memperbaiki bug dalam logika, tetapi di sepanjang jalan ia menemukan beberapa kekurangan di antarmuka. "Yah, karena aku tetap mengerjakan bagian ini," pikirnya, "Aku akan memperbaikinya pada saat yang sama." Akibatnya, kebingungan pun dimulai. Peninjau sekarang harus mencari tahu perubahan mana yang berhasil untuk tugas A dan mana yang berfungsi untuk tugas B.



Kumpulan perubahan terbaik melakukan satu hal . Semakin tepat dan sederhana perubahannya, semakin mudah bagi inspektur untuk mengingat konteksnya. Dengan berbagi perubahan yang tidak terkait, Anda juga mendapatkan kemampuan untuk memiliki beberapa rekan meninjau secara paralel, yang berarti kode Anda akan kembali kepada Anda lebih cepat.



6. Pisahkan



perubahan fungsional dan non-fungsional Aturan lain mengikuti dari batasan skala - perubahan fungsional dan non-fungsional tidak boleh dicampur.



Pengembang dengan sedikit pengalaman dengan pemeriksaan kode sering melanggar aturan ini. Mereka membuat semacam perubahan kerusakan, dan editor kode segera mengubah format di seluruh file. Pengembang tidak memahami apa yang terjadi, atau memutuskan itu lebih baik dan mengirimkan kode di mana satu perubahan fungsional terkubur di bawah ratusan baris yang tidak berfungsi.







Apakah Anda akan menemukan perubahan fungsional?



Kebingungan seperti itu seperti ludah di hadapan seorang inspektur. Perubahan format saja mudah diperiksa. Perubahan fungsional juga. Satu gangguan fungsional dalam lautan perubahan format bisa jadi sia-sia dan gila.



Selain itu, pengembang suka menggabungkan pemfaktoran ulang menjadi perubahan besar pada waktu yang tepat. Saya sangat menyetujui pemfaktoran ulang kode dari pihak kolega, tetapi tidak ketika mereka secara bersamaan menerapkan perilaku baru.







Perubahan perilaku terkubur di tengah-tengah pemfaktoran ulang



Jika sepotong kode membutuhkan pemfaktoran ulang dan perubahan perilaku, Anda perlu memecah proses menjadi dua atau tiga set:



  1. Tambahkan pengujian untuk perilaku saat ini (jika tidak ada)
  2. Refactor kode tanpa mengubah apa pun dalam pengujian


Dengan menjaga agar pengujian tetap utuh di tahap kedua, peninjau dapat memastikan bahwa pemfaktoran ulang tidak melanggar perilaku. Karenanya, pada tahap ketiga, dia tidak perlu memikirkan apa yang refactoring di sini, dan apa yang berfungsi untuk mengubah perilaku - lagipula, Anda telah memisahkan satu sama lain sebelumnya.



7. Hentikan perubahan yang terlalu besar



Perubahan yang membengkak seperti sepupu jelek dari batas yang luas . Bayangkan sebuah situasi: pengembang sampai pada kesimpulan bahwa untuk mengimplementasikan fungsionalitas A, pertama-tama dia harus memperbaiki semantik pustaka B dan C. Jika ada sedikit perubahan, apa pun yang terjadi, tetapi sangat sering modifikasi ini menyebar dan hasilnya adalah daftar perubahan yang sangat besar.



Kompleksitas log perubahan tumbuh secara eksponensial dengan jumlah baris yang terpengaruh. Jika perubahan mempengaruhi 400 baris atau lebih, saya mencari cara untuk memotongnya sebelum meminta pemeriksaan.



Mungkin alih-alih melakukan semuanya sekaligus, akan mungkin untuk bekerja dengan dependensi terlebih dahulu, dan di set berikutnya, mengimplementasikan fungsionalitas baru? Apakah realistis untuk menjaga kode tetap waras jika Anda menerapkan setengah dari fungsionalitas sekarang dan setengah lainnya di fase berikutnya?



Berpikir tentang cara memecah kode untuk mendapatkan bagian yang berfungsi dan dapat dipahami bisa jadi membosankan. Namun hal ini memungkinkan adanya umpan balik yang lebih baik dan mengurangi kerumitan bagi pengulas.



8. Terima kritik dengan baik



Cara paling pasti untuk merusak seluruh ujian adalah menerima kritik dengan sikap bermusuhan. Sulit untuk menolak, karena banyak pengembang bangga dengan apa yang mereka lakukan dan menganggap pekerjaan mereka sebagai perpanjangan dari diri mereka sendiri. Dan jika inspektur membuat komentar yang tidak bijaksana atau mendatangi orang , ini semakin memperumit masalah.



Pada akhirnya, Anda, sebagai penulis, bebas menentukan cara Anda menanggapi komentar. Perlakukan kata-kata inspektur sebagai diskusi objektif tentang kode yang tidak ada hubungannya dengan penilaian kepribadian Anda. Jika Anda bersikap defensif, itu hanya akan bertambah buruk.



Saya mencoba mengambil komentar apapun sebagai upaya untuk membantu dan mendapatkan keuntungan. Jika peninjau menemukan kesalahan bodoh dalam kode, saya secara naluriah tertarik untuk mulai membuat alasan. Tapi saya menahan diri dan memuji pengamatannya.







- Untuk Januari dan Februari 1900, tidak akan berhasil.

- Tepat, diperhatikan dengan baik!




Anehnya, fakta bahwa inspektur menemukan kekurangan yang tidak terlihat dalam kode adalah pertanda baik. Ini menunjukkan bahwa Anda pandai menyiapkan file untuk dipindai. Dengan tidak adanya pemformatan yang ceroboh, nama buruk, dan hal-hal mencolok lainnya, peninjau dapat mendalami logika dan desain serta membuat pengamatan yang lebih berharga.



9. Bersabarlah jika inspektur membuat kesalahan



Dari waktu ke waktu, inspektur keliru. Dia dapat salah membaca kode normal dan Anda dapat menanam bug. Banyak pengembang dalam kasus seperti itu mulai membela diri dengan keras. Mereka tersinggung karena seseorang mengkritik karyanya, dan bahkan tidak berdasarkan apa pun.



Namun, meskipun peninjau salah, Anda masih harus memikirkan banyak hal. Jika dia salah membaca sesuatu, apa kemungkinan orang lain akan membuat kesalahan yang sama di masa depan? Bukankah pembaca harus mempelajari kode tersebut bolak-balik, hanya untuk memastikan bahwa bug yang mereka lihat tidak ada di sini?







- Ada buffer overflow di sini, karena tidak dilakukan verifikasi apakah ada cukup memori dalam nama untuk menampung semua karakter NewNameLen.

- Apakah itu ada dalam kodeku? Tak terpikirkan! Konstruktor memanggil PurchaseHats, dan memanggil CheckWeather, yang akan memunculkan kesalahan jika panjang buffer tidak cocok. Pertama-tama Anda akan membaca 200.000 baris kode dan kemudian berani mengakui kemungkinan bahwa saya salah di suatu tempat.




Pikirkan tentang cara refactor, atau tambahkan komentar sehingga sekilas Anda dapat memahami bahwa semuanya beres di sini. Jika kesalahpahaman bermula dari penggunaan fitur-fitur bahasa yang jarang diketahui, tulis ulang kode menggunakan mekanisme yang tidak memerlukan pengetahuan menyeluruh.



10. Berikan reaksi yang dapat dimengerti



Saya sering menemukan diri saya dalam situasi ini: Saya mengirim komentar kepada seseorang, dia memperbarui kode dengan mempertimbangkan beberapa di antaranya, tetapi pada saat yang sama dia tetap diam. Ada masa ketidakpastian. Entah dia melewatkan sisa komentar, atau masih dalam proses mengoreksi. Jika Anda mulai memeriksa apa yang telah dilakukan, secara hipotetis, mungkin ternyata potongan kode ini masih berfungsi dan saya membuang-buang waktu. Jika kita menunggu, kita bisa menemui jalan buntu - kita berdua akan duduk dan menunggu langkah selanjutnya dari satu sama lain.



Tetapkan urutan tindakan tertentu dalam tim sehingga selalu jelas siapa yang memegang "tongkat estafet" saat ini. Prosesnya tidak boleh dibiarkan melambat hanya karena tidak ada yang mengerti apa yang sedang terjadi. Ini mudah dilakukan - cukup tinggalkan komentar di tingkat set perubahan, dari mana sudah jelas kapan hak untuk bertindak ditransfer ke peserta lain.







Memperbaiki tajuk> Memperbarui kode sesuai dengan komentar> Semuanya sudah siap, silakan lihat.



Setiap komentar yang mengharuskan Anda mengambil tindakan harus ditanggapi dengan mengonfirmasi bahwa Anda telah melakukannya. Beberapa alat pemeriksaan kode menyediakan kemampuan untuk menandai komentar yang diproses. Jika tidak, gunakan kumpulan poin teks sederhana seperti Selesai. Jika Anda tidak setuju dengan komentar tersebut, jelaskan dengan sopan mengapa Anda memutuskan untuk tidak mengoreksi.







Beberapa alat seperti Reviewable dan Gerritt menyarankan pemberian tag pada komentar yang sudah diproses



. Seimbangkan reaksi Anda dengan upaya pengulas. Jika dia telah merinci suatu momen sehingga Anda dapat mempelajari sesuatu yang baru untuk diri Anda sendiri, jangan batasi diri Anda pada tanda “Selesai”. Jawablah dengan serius untuk menunjukkan bahwa Anda menghargai karyanya.



11. Dengan terampil mengumpulkan informasi yang hilang



Kadang-kadang komentar inspektur menyisakan terlalu banyak ruang untuk interpretasi. Ketika mereka menulis kepada Anda sesuatu dengan semangat "Saya tidak mengerti fungsi ini," muncul pertanyaan, apa sebenarnya yang tidak jelas bagi seseorang. Terlalu panjang? Nama yang buruk? Perlu dokumen yang lebih baik?



Untuk waktu yang lama saya bertanya-tanya bagaimana mengklarifikasi komentar yang tidak jelas dan tidak secara tidak sengaja terlibat dalam konfrontasi. Hal pertama yang terlintas di benak saya adalah bertanya: "Apa yang tidak bisa dimengerti dalam dirinya?", Tapi itu terdengar galak.



Saya pernah dengan sengaja mengirim balasan yang tidak jelas kepada rekan semacam ini, dan dia melucuti saya dengan jawabannya:



"Apa yang bisa diubah untuk membuatnya lebih baik?"


Saya suka frasa ini karena mengungkapkan keterbukaan terhadap kritik dan kurangnya permusuhan. Sekarang, ketika saya mendapat tanggapan yang tidak jelas, saya menanggapi dengan beberapa variasi motif dasar "Apa yang harus diubah agar lebih baik?"



Teknik lain yang berguna adalah mencoba menebak apa yang dimaksudkan pengulas dan memimpin dalam mengoreksi kode yang sesuai. Jika Anda mendapatkan komentar yang "tidak dapat dipahami", lihat lebih dekat kodenya. Biasanya ditemukan sesuatu yang dapat ditingkatkan dalam hal kejelasan. Hasil edit memberi tahu inspektur bahwa Anda siap untuk membuat perubahan, meskipun mereka memiliki gagasan berbeda tentang hasil akhirnya.



12. Berikan prioritas kepada reviewer



Dalam tenis, jika tidak sepenuhnya jelas apakah bola keluar dari batas saat melakukan servis kepada lawan, biasanya menafsirkan situasi yang menguntungkannya. Aturan ini juga harus diikuti saat memeriksa kode Anda.



Beberapa keputusan desain adalah masalah selera. Jika pengkaji berpikir bahwa fungsi sepuluh baris Anda akan lebih baik dibagi menjadi dua fungsi lima baris, kebenaran obyektif bukanlah milik Anda atau miliknya. Opsi mana yang lebih baik tergantung pada preferensi.



Jika inspektur membuat proposal dan argumen yang mendukung posisinya kira-kira sama untuk Anda, terimalah sudut pandangnya. Lagi pula, di antara Anda berdua, dialah yang mendapat manfaat dari melihat kode baru.



13. Kurangi waktu transfer kode



Beberapa bulan yang lalu, pengguna membuat perubahan kecil pada proyek open source yang saya pelihara. Saya berhenti berlangganan dengan komentar beberapa jam kemudian, tetapi dia sudah menghilang dengan ujungnya. Beberapa hari kemudian saya kembali dan menemukan bahwa masih belum ada jawaban.



Enam minggu kemudian, pengembang misterius muncul kembali di proyek dengan revisi. Meskipun saya menghargai karyanya, jeda panjang antara dua tahap verifikasi mengarah pada fakta bahwa saya menghabiskan tenaga dua kali lebih banyak untuk pemeriksaan. Saya harus membaca ulang tidak hanya kode, tetapi juga komentar saya sendiri untuk mengingat apa yang umumnya dibahas. Jika orang tersebut muncul dalam beberapa hari, tidak perlu ada pekerjaan tambahan.







Biaya intelektual untuk pemeriksaan kode dengan waktu transmisi pendek (kiri) dan panjang (kanan)

Sumbu x adalah waktu; sumbu y - memori inspektur; naungan biru - pemulihan konteks; isi biru - cek kode; isi abu-abu - menunggu; bayangan merah - biaya tambahan




Enam minggu, tentu saja, merupakan kasus yang luar biasa, tetapi saya sering melihat jeda yang lama dan tidak dapat dibenarkan dalam tim saya. Seseorang mengirimkan sekumpulan perubahan untuk ditinjau, mendapat umpan balik, dan menunda pengeditan selama seminggu karena mereka terganggu oleh tugas lain.



Selain fakta bahwa nanti Anda harus menghabiskan waktu untuk memulihkan konteks, fragmen kode setengah jadi menciptakan kompleksitas. Mereka membuat lebih sulit untuk melacak apa yang sudah dikeringkan dan yang belum. Semakin banyak daftar perubahan yang diproses sebagian, semakin tinggi kemungkinan konflik penggabungan, dan tidak ada yang suka mengacaukannya.



Setelah Anda mengirimkan kode untuk diperiksa, prioritas utama Anda adalah menindaklanjutinya. Jika proses terhenti karena kesalahan Anda, maka Anda mencuri waktu inspektur dan memperumit hidup seluruh tim.



Akhirnya



Saat Anda mempersiapkan changelog berikutnya untuk pengiriman, pertimbangkan faktor apa yang dapat Anda tangani dan gunakan peluang tersebut untuk membuat ulasan menjadi produktif. Saat Anda berpartisipasi dalam peninjauan kode, periksa hal-hal yang secara teratur memperlambat proses dan membuang sumber daya.



Ingat aturan emas: hargai waktu pengulas. Jika Anda memberinya kesempatan untuk fokus pada bagian kode yang benar-benar menarik, komentarnya akan berguna. Jika Anda memaksanya untuk membuang-buang waktu untuk hal-hal sepele atau mengurai kebingungan, itu akan berdampak buruk bagi Anda berdua.



Terakhir, pikirkan baik-baik jawaban Anda. Kesalahpahaman tentang hal-hal sepele atau kata-kata yang sembrono dapat menggagalkan hal-hal dengan kecepatan yang mengkhawatirkan. Semangat tinggi ketika mengkritik pekerjaan orang lain, jadi hati-hati hindari apa pun yang dapat membuat penguji berpikir bahwa Anda menyerangnya atau memperlakukannya tanpa rasa hormat.



Selamat! Jika Anda telah membaca sejauh ini, Anda mungkin sudah menganggap diri Anda ahli pemeriksaan kode. Inspektur Anda kemungkinan besar sudah terbakar, jadi Anda memperlakukan mereka secara manusiawi.



All Articles