Artikel ini dikaji semula oleh Tom Greco, Dan Prince dan Yaphi Berhanu. Terima kasih kepada semua pengulas rakan sebaya SitePoint untuk membuat kandungan SitePoint yang terbaik boleh!
Hampir setiap pemaju mempunyai pengalaman mengekalkan atau mengambil alih projek warisan. Atau, mungkin ia adalah satu projek lama yang dijemput lagi. Pemikiran pertama yang biasa adalah membuang asas kod, dan bermula dari awal. Kod ini boleh menjadi kemas, tidak berdokumen dan boleh mengambil masa beberapa hari untuk memahami sepenuhnya segala -galanya. Tetapi, dengan perancangan, analisis, dan aliran kerja yang baik, adalah mungkin untuk menjadikan asas spageti menjadi satu yang bersih, teratur, dan berskala.Saya terpaksa mengambil alih dan membersihkan banyak projek. Tidak banyak yang saya mulakan dari awal. Malah, saya sedang melakukan perkara itu. Saya telah belajar banyak mengenai JavaScript, menyimpan asas kod yang dianjurkan dan - yang paling penting -
tidak gila pada pemaju sebelumnya. Dalam artikel ini saya ingin menunjukkan kepada anda langkah saya dan memberitahu anda pengalaman saya.
Ketahui alat mana yang sedang digunakan. jQuery? Bertindak balas? Menyatakan? Buat senarai semua yang penting untuk diketahui. Katakan projek itu ditulis dalam Angular 2 dan anda tidak bekerja dengan itu, pergi terus ke dokumentasi dan dapatkan pemahaman asas. Cari amalan terbaik.
memahami projek pada tahap yang lebih tinggi
Ini adalah mengenai penubuhan konsistensi. Sekarang bahawa anda mempunyai semua maklumat mengenai alat -alat toolchain, anda tahu struktur dan bagaimana logik disambungkan, sudah tiba masanya untuk membuat garis dasar. Saya cadangkan menambah fail .editorconfig untuk memastikan panduan gaya pengekodan konsisten antara editor, IDE, dan pemaju yang berbeza.
Soalan yang terkenal (ia agak perang walaupun), sama ada ruang atau tab harus digunakan, tidak penting. Adakah codebase ditulis dalam ruang? Teruskan dengan ruang. Dengan tab? Gunakannya. Hanya apabila codebase mempunyai lekukan campuran adalah perlu untuk menentukan yang hendak digunakan. Pendapatnya baik -baik saja, tetapi projek yang baik memastikan semua pemaju dapat berfungsi tanpa kerumitan.
Kenapa ini penting? Setiap orang mempunyai cara sendiri menggunakan editor atau IDE. Sebagai contoh, saya peminat besar lipat kod. Tanpa ciri itu, saya benar -benar hilang dalam fail. Apabila lekukan tidak koheren, ciri -ciri ini gagal. Jadi setiap kali saya membuka fail, saya perlu menetapkan lekukan sebelum saya dapat mula bekerja. Ini adalah pembaziran masa yang besar.
<span>// While this is valid JavaScript, the block can't </span><span>// be properly folded due to its mixed indentation. </span> <span>function foo (data) { </span> <span>let property = String(data); </span> <span>if (property === 'bar') { </span> property <span>= doSomething(property); </span> <span>} </span> <span>//... more logic. </span> <span>} </span> <span>// Correct indentation makes the code block foldable, </span><span>// enabling a better experience and clean codebase. </span><span>function foo (data) { </span> <span>let property = String(data); </span> <span>if (property === 'bar') { </span> property <span>= doSomething(property); </span> <span>} </span> <span>//... more logic. </span><span>} </span>
Pastikan konvensyen penamaan yang digunakan dalam projek dihormati. Camelcase biasanya digunakan dalam kod JavaScript, tetapi saya telah melihat banyak konvensyen campuran. Sebagai contoh, projek jQuery sering mempunyai penamaan campuran pembolehubah objek jQuery dan pembolehubah lain.
<span>// Inconsistent naming makes it harder </span><span>// to scan and understand the code. It can also </span><span>// lead to false expectations. </span><span>const $element = $('.element'); </span> <span>function _privateMethod () { </span> <span>const self = $(this); </span> <span>const _internalElement = $('.internal-element'); </span> <span>let $data = element.data('foo'); </span> <span>//... more logic. </span><span>} </span> <span>// This is much easier and faster to understand. </span><span>const $element = $('.element'); </span> <span>function _privateMethod () { </span> <span>const $this = $(this); </span> <span>const $internalElement = $('.internal-element'); </span> <span>let elementData = $element.data('foo'); </span> <span>//... more logic. </span><span>} </span>
Walaupun langkah -langkah sebelumnya lebih kosmetik dan terutamanya untuk membantu mengimbas kod lebih cepat, di sini kami memperkenalkan dan memastikan amalan terbaik yang sama serta kualiti kod. Eslint, JSLint, dan JSHint adalah linter JavaScript yang paling popular pada hari ini. Secara peribadi, saya pernah bekerja dengan JSHint banyak, tetapi Eslint telah mula menjadi kegemaran saya, terutamanya kerana peraturan tersuai dan sokongan ES2015 awal.
Apabila anda mula menyentuh, jika banyak kesilapan muncul, selesaikannya! Jangan teruskan dengan apa -apa lagi sebelum linter anda gembira!
Mengemas kini kebergantungan perlu dilakukan dengan teliti. Sangat mudah untuk memperkenalkan lebih banyak kesilapan apabila tidak memberi perhatian kepada perubahan kebergantungan anda. Sesetengah projek mungkin berfungsi dengan versi tetap (mis. V1.12.5), manakala yang lain menggunakan versi wildcard (mis. V1.12.x). Sekiranya anda memerlukan kemas kini yang cepat, nombor versi dibina seperti berikut: Major.minor.patch. Jika anda tidak biasa dengan cara kerja versi semantik, saya cadangkan membaca artikel ini oleh Tim Oxley.
Tidak ada peraturan umum untuk mengemas kini kebergantungan. Setiap projek adalah berbeza dan harus dikendalikan seperti itu. Mengemas kini nombor patch kebergantungan anda tidak sepatutnya menjadi masalah sama sekali, dan kecil juga baik -baik saja. Hanya apabila anda membongkar jumlah besar kebergantungan anda, anda harus mencari apa yang sebenarnya telah berubah. Mungkin API telah berubah sepenuhnya dan anda perlu menulis semula sebahagian besar aplikasi anda. Jika itu tidak bernilai usaha, saya akan mengelakkan mengemaskini versi utama seterusnya.
Jika projek anda menggunakan NPM sebagai Pengurus Ketergantungan (dan tidak ada pesaing), anda boleh menyemak apa -apa kebergantungan yang sudah lapuk dengan perintah NPM yang sudah lapuk dari CLI anda. Izinkan saya menggambarkan ini dengan contoh dari salah satu projek saya yang dipanggil Frontbook, di mana saya sering mengemas kini semua kebergantungan:
mari kita dapatkan tangan kita kotor
Mewujudkan ujian unit
Perbezaan antara ujian unit dan automasi penyemak imbas adalah, bahawa bekas menguji kod JavaScript anda sendiri. Ia memastikan semua modul anda dan kerja logik umum seperti yang dimaksudkan. Automasi penyemak imbas, sebaliknya, menguji permukaan - antara muka pengguna - projek anda, memastikan unsur -unsur berada di tempat yang betul dan berfungsi seperti yang diharapkan.
Jaga ujian unit sebelum anda memulakan refactoring apa -apa lagi. Kestabilan projek anda akan bertambah baik, dan anda tidak pernah memikirkan skalabiliti! Kesan sampingan yang hebat tidak bimbang sepanjang masa yang anda mungkin telah memecahkan sesuatu dan tidak perasan.
Rebecca Murphey Seperti yang ditulis artikel yang sangat baik mengenai ujian unit penulisan untuk JavaScript sedia ada.
Senibina JavaScript adalah satu lagi topik besar. Refactoring dan membersihkan seni bina beralih kepada berapa banyak pengalaman yang anda miliki dengan melakukan itu. Kami mempunyai banyak corak reka bentuk yang berbeza dalam pembangunan perisian, tetapi tidak semuanya sesuai dengan skalabilitas. Malangnya saya tidak akan dapat menampung semua kes dalam artikel ini, tetapi sekurang -kurangnya boleh memberi anda nasihat umum.
Pertama sekali, anda harus mengetahui corak reka bentuk mana yang sudah digunakan dalam projek anda. Baca tentang corak, dan pastikan ia konsisten. Salah satu kunci untuk berskala adalah berpegang pada corak, dan bukan metodologi pencampuran. Sudah tentu, anda boleh mempunyai corak reka bentuk yang berbeza untuk tujuan yang berbeza dalam projek anda (mis. Menggunakan corak singleton untuk struktur data atau fungsi penolong nama pendek, dan corak pemerhati untuk modul anda) tetapi tidak boleh menulis satu modul dengan satu corak, dan yang lain satu dengan corak yang berbeza.
Jika tidak ada seni bina dalam projek anda (mungkin semuanya hanya dalam satu app.js yang besar), sudah tiba masanya untuk mengubahnya. Jangan lakukan semuanya sekaligus, tetapi sekeping sekeping. Sekali lagi, tidak ada cara generik untuk melakukan sesuatu dan setiap persediaan projek adalah berbeza. Struktur folder berbeza antara projek, bergantung kepada saiz dan kerumitan. Biasanya-pada tahap yang sangat asas-strukturnya dibahagikan kepada perpustakaan, modul, data dan titik masuk (misalnya index.js, main.js) di mana semua modul dan logik anda akan dimulakan.
ini membawa saya ke modularization.
Modularization adalah setakat ini bukan jawapan kepada soalan skalabiliti JavaScript yang hebat. Ia menambah satu lagi lapisan API yang pemaju perlu mengenali. Ini boleh menjadi masalah. Prinsip ini memisahkan semua fungsi anda ke modul kecil. Dengan melakukan itu, lebih mudah untuk menyelesaikan masalah dalam kod anda dan bekerja dalam satu pasukan di pangkalan yang sama. Setiap modul harus mempunyai satu tujuan dan tugas yang perlu dilakukan. Modul tidak tahu mengenai logik luar permohonan anda, dan boleh digunakan semula di lokasi dan situasi yang berbeza.
Bagaimana anda membahagikan ciri besar dengan banyak logik yang berkaitan dengan ketat? Mari buat ini bersama -sama.
<span>// While this is valid JavaScript, the block can't </span><span>// be properly folded due to its mixed indentation. </span> <span>function foo (data) { </span> <span>let property = String(data); </span> <span>if (property === 'bar') { </span> property <span>= doSomething(property); </span> <span>} </span> <span>//... more logic. </span> <span>} </span> <span>// Correct indentation makes the code block foldable, </span><span>// enabling a better experience and clean codebase. </span><span>function foo (data) { </span> <span>let property = String(data); </span> <span>if (property === 'bar') { </span> property <span>= doSomething(property); </span> <span>} </span> <span>//... more logic. </span><span>} </span>
Ini tidak begitu modular. Segala -galanya dihubungkan dengan ketat dan bergantung pada kepingan lain. Bayangkan ini dengan fungsi yang lebih besar dan lebih kompleks dan anda perlu debug ini kerana sesuatu yang pecah. Mungkin API tidak bertindak balas, sesuatu yang berubah di dalam JSON atau apa sahaja. Mimpi ngeri, bukan?
mari kita memisahkan tanggungjawab yang berbeza:
<span>// Inconsistent naming makes it harder </span><span>// to scan and understand the code. It can also </span><span>// lead to false expectations. </span><span>const $element = $('.element'); </span> <span>function _privateMethod () { </span> <span>const self = $(this); </span> <span>const _internalElement = $('.internal-element'); </span> <span>let $data = element.data('foo'); </span> <span>//... more logic. </span><span>} </span> <span>// This is much easier and faster to understand. </span><span>const $element = $('.element'); </span> <span>function _privateMethod () { </span> <span>const $this = $(this); </span> <span>const $internalElement = $('.internal-element'); </span> <span>let elementData = $element.data('foo'); </span> <span>//... more logic. </span><span>} </span>
baiklah, kami mempunyai tiga modul baru sekarang. Mari kita lihat panggilan refactored.
<span>// This example uses the Fetch API to request an API. Let's assume </span><span>// that it returns a JSON file with some basic content. We then create a </span><span>// new element, count all characters from some fictional content </span><span>// and insert it somewhere in your UI. </span><span>fetch('https://api.somewebsite.io/post/61454e0126ebb8a2e85d', { method: 'GET' }) </span> <span>.then(response => { </span> <span>if (response.status === 200) { </span> <span>return response.json(); </span> <span>} </span> <span>}) </span> <span>.then(json => { </span> <span>if (json) { </span> <span>Object.keys(json).forEach(key => { </span> <span>const item = json[key]; </span> <span>const count = item.content.trim().replace(<span>/<span>\s+</span>/gi</span>, '').length; </span> <span>const el = <span>` </span></span><span><span> <div token interpolation"><span>${item.className}</span>"> </span></span><span><span> <p>Total characters: <span>${count}</span></p> </span></span><span><span> </div> </span></span><span><span> `</span>; </span> <span>const wrapper = document.querySelector('.info-element'); </span> wrapper<span>.innerHTML = el; </span> <span>}); </span> <span>} </span> <span>}) </span> <span>.catch(error => console.error(error)); </span>
kita juga boleh mengambil logik dari dalam.
Seperti yang telah saya sebutkan, bertukar pangkalan kod anda dalam modul kecil menambah lapisan API yang lain. Jika anda tidak mahu itu, tetapi ingin memastikan lebih mudah bagi pemaju lain untuk bekerja dengan kod anda, ia adalah baik untuk memastikan fungsi lebih besar. Anda masih boleh memecahkan kod anda ke bahagian yang lebih mudah dan lebih fokus pada kod yang boleh diuji.
Dokumentasi adalah topik yang banyak dibincangkan. Salah satu bahagian penyokong komuniti pengaturcaraan untuk mendokumentasikan segala-galanya, sementara kumpulan lain menganggap kod dokumentasi diri adalah cara untuk pergi. Seperti kebanyakan perkara dalam hidup, saya fikir keseimbangan yang baik kedua -duanya membuat kod boleh dibaca dan berskala. Gunakan JSDOC untuk dokumentasi anda.
JSDOC adalah penjana dokumentasi API untuk JavaScript. Ia biasanya tersedia sebagai plugin untuk semua editor dan IDE yang terkenal. Mari kita melalui contoh:
<span>// While this is valid JavaScript, the block can't </span><span>// be properly folded due to its mixed indentation. </span> <span>function foo (data) { </span> <span>let property = String(data); </span> <span>if (property === 'bar') { </span> property <span>= doSomething(property); </span> <span>} </span> <span>//... more logic. </span> <span>} </span> <span>// Correct indentation makes the code block foldable, </span><span>// enabling a better experience and clean codebase. </span><span>function foo (data) { </span> <span>let property = String(data); </span> <span>if (property === 'bar') { </span> property <span>= doSomething(property); </span> <span>} </span> <span>//... more logic. </span><span>} </span>
Fungsi ini mengambil dua parameter dan melangkah ke atas objek, yang kemudiannya mengembalikan array. Ini mungkin bukan kaedah yang terlalu rumit, tetapi bagi seseorang yang tidak menulis kod yang mungkin mengambil sedikit masa untuk mengetahui apa yang sedang berlaku. Di samping itu, tidak jelas apa kaedahnya. Mari mula mendokumentasikan:
<span>// Inconsistent naming makes it harder </span><span>// to scan and understand the code. It can also </span><span>// lead to false expectations. </span><span>const $element = $('.element'); </span> <span>function _privateMethod () { </span> <span>const self = $(this); </span> <span>const _internalElement = $('.internal-element'); </span> <span>let $data = element.data('foo'); </span> <span>//... more logic. </span><span>} </span> <span>// This is much easier and faster to understand. </span><span>const $element = $('.element'); </span> <span>function _privateMethod () { </span> <span>const $this = $(this); </span> <span>const $internalElement = $('.internal-element'); </span> <span>let elementData = $element.data('foo'); </span> <span>//... more logic. </span><span>} </span>
Saya tidak menyentuh banyak kod itu sendiri. Hanya dengan menamakan semula fungsi dan menambah blok komen yang pendek, namun terperinci, kami telah meningkatkan kebolehbacaan.
Refactoring adalah misi besar sendiri. Untuk sentiasa menggulung perubahan anda (sekiranya anda memecahkan sesuatu dan hanya notis kemudian), saya cadangkan melakukan setiap kemas kini yang anda buat. Tulis semula kaedah? komited git (atau SVN komit, jika anda bekerja dengan SVN). Namakan semula ruang nama, folder atau beberapa imej? git komit. Anda mendapat idea itu. Ia mungkin membosankan bagi sesetengah orang, tetapi ia benar -benar membantu anda membersihkan dengan betul dan teratur.
Buat cawangan baru untuk keseluruhan usaha refactoring. Jangan pernah bekerja pada Guru! Anda mungkin perlu melakukan perubahan cepat atau memuat naik pembetulan pepijat ke persekitaran pengeluaran dan anda tidak mahu menggunakan kod anda (mungkin belum diuji) sehingga ia diuji dan selesai. Oleh itu, dinasihatkan untuk sentiasa bekerja di cawangan yang berbeza.
Sekiranya anda memerlukan kemas kini ringkas bagaimana semua ini berfungsi, terdapat panduan menarik dari GitHub pada aliran kerja kawalan versi mereka.
Selain semua langkah teknikal yang diperlukan untuk pembersihan, terdapat satu langkah penting yang jarang saya lihat di mana-mana: tidak marah pada pemaju sebelumnya. Sudah tentu, ini tidak berlaku untuk semua orang, tetapi saya tahu bahawa sesetengah orang mengalami ini. Saya mengambil masa bertahun -tahun untuk benar -benar memahami perkara ini dan mengatasinya. Saya pernah menjadi sangat marah pada kod pemaju sebelumnya, penyelesaian mereka dan mengapa segala -galanya adalah kekacauan seperti itu.
Pada akhirnya, semua negatif yang tidak pernah mendapat saya di mana -mana sahaja. Ia hanya mengakibatkan anda refactoring lebih daripada yang diperlukan, membuang masa anda, dan mungkin memecahkan perkara. Ini hanya menjadikan anda lebih kesal. Anda mungkin menghabiskan masa tambahan dan tiada siapa yang akan mengucapkan terima kasih kerana menulis semula modul yang sudah bekerja. Ia tidak berbaloi. Lakukan apa yang diperlukan, menganalisis keadaan. Anda sentiasa boleh refactor bit kecil setiap kali anda kembali ke modul.
Selalu ada sebab mengapa kod ditulis seperti itu. Mungkin pemaju sebelumnya tidak mempunyai cukup masa untuk melakukannya dengan betul, tidak tahu lebih baik, atau apa sahaja. Kita semua ada di sana.
mari kita pergi ke semua langkah lagi, untuk membuat senarai semak untuk projek anda yang seterusnya.
Saya sangat berharap artikel ini telah membantu anda. Izinkan saya tahu jika anda berjuang dengan mana -mana langkah, atau mungkin mempunyai nasihat yang baik yang saya tidak sebutkan!
Apakah beberapa perangkap biasa untuk dielakkan ketika menulis kod JavaScript? Sertakan tidak menggunakan mod yang ketat, tidak mengisytiharkan pembolehubah dengan betul, menggunakan pengendali '==' bukan '===', dan tidak mengendalikan kesilapan dengan betul. Mengelakkan perangkap ini dapat membantu anda menulis kod yang lebih bersih, lebih banyak yang dapat dipelihara. Pertama, anda perlu memahami kod sedia ada. Ini mungkin melibatkan membaca melalui kod dan mendokumentasikan apa yang dilakukan oleh setiap bahagian. Kedua, mengenal pasti bidang kod yang dapat ditingkatkan. Ini boleh menjadi bahagian kod yang diulang, logik bersyarat kompleks, atau kod yang sukar difahami. Ketiga, buat perubahan yang diperlukan pada kod. Ini mungkin melibatkan memecahkan fungsi kompleks ke dalam yang lebih kecil, lebih mudah diurus, mengeluarkan kod pendua, atau menulis semula bahagian kod untuk menjadikannya lebih mudah difahami. Akhir sekali, uji perubahan anda untuk memastikan bahawa fungsi kod tetap sama.
Betapa pentingnya mengulas dalam mengekalkan kod JavaScript? kod. Ia membantu pemaju lain (dan masa depan anda) memahami apa kod yang dilakukan dan mengapa keputusan tertentu dibuat. Ini amat penting dalam codebase kompleks, di mana pemahaman fungsi kod boleh mencabar. Walau bagaimanapun, komen harus digunakan dengan bijak. Kenyataan yang lebih tinggi boleh membuat kod berantakan dan lebih sukar untuk dibaca. Sebaik-baiknya, kod anda harus jelas, dengan komen yang dikhaskan untuk menjelaskan mengapa keputusan tertentu dibuat atau menjelaskan bahagian kod kompleks. Kod JavaScript anda berskala melibatkan merancang kod anda dengan cara yang membolehkannya mengendalikan peningkatan beban dengan cekap. Ini dapat dicapai dengan mengikuti amalan pengaturcaraan yang baik seperti menggunakan algoritma dan struktur data yang cekap, mengelakkan pembolehubah global, dan meminimumkan manipulasi DOM. Di samping itu, dengan menggunakan pendekatan modular untuk pengekodan, di mana kod anda dipecahkan ke dalam kepingan yang lebih kecil, boleh diguna semula, juga dapat meningkatkan skalabilitas. Ujian memainkan peranan penting dalam menulis kod JavaScript yang boleh dipelihara. Ia membantu memastikan kod anda berfungsi seperti yang diharapkan dan dapat membantu menangkap pepijat awal dalam proses pembangunan. Terdapat beberapa jenis ujian yang boleh anda gunakan, termasuk ujian unit, ujian integrasi, dan ujian akhir-ke-akhir. Menggunakan gabungan kaedah ujian ini dapat membantu memastikan kod anda teguh dan boleh dipercayai.
Atas ialah kandungan terperinci Kod Spaghetti Untangling: Menulis JavaScript yang Boleh Dipelihara. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!