Elemen Fraktal

Halo, nama saya ... Sobat. Jumlah tangan adalah 2. Jumlah kaki adalah 2. Golongan darah adalah 1. Rhesus benar.


Tampaknya bagi Anda bahwa hanya dengan informasi ini, tanpa nama, nama keluarga atau bahkan nama panggilan, sulit untuk membedakan saya dari banyak penulis artikel lainnya. Dan kamu akan benar. Namun, di ujung depan, saya sering melihat bagaimana nama elemen digantikan oleh deskripsinya. Dan tidak ada yang peduli.


Tiga pria dan seorang gadis


Duduklah, perjalanan yang menarik menanti Anda di depan masalah serius proyek-proyek serius, yang, bagaimanapun, sering dianggap remeh.


Tes


Bayangkan diri Anda sebagai penulis tes ujung ke ujung otomatis. Anda perlu menguji itu, misalnya, di Yandex di sudut kanan atas nama yang benar dari pengguna yang masuk ditampilkan.


Moncong Yandex melalui mata admin


Berikan halaman ini ke desainer tata letak yang khas dan dia akan memberi Anda sesuatu seperti ini:


<body> <aside> <div class="card"> <div class="username">admin</div> </div> <!-- -  --> </aside> <section> <!-- -  --> </section> </body> 

Isi ulang pertanyaan: bagaimana menemukan elemen rumah tempat nama pengguna ditampilkan?


Dua cara, tetapi esensinya adalah satu


Di sini penguji memiliki dua pilihan kursi:


  1. Tuliskan pemilih css atau xpath pada formulir di aside > .card > .username dan berdoalah agar tidak ada kartu lain yang akan muncul di sidebar. Dan tidak ada nama pengguna lain yang muncul di kartu. Dan agar tidak ada yang mengubahnya ke tombol apa pun. Dan dia tidak membungkusnya dengan soket apa pun. Singkatnya, ini adalah pemilih yang sangat rapuh, yang penggunaannya akan mematahkan tes dengan sedikit perubahan pada halaman.
  2. Minta pengembang untuk menambahkan pengidentifikasi unik untuk halaman tersebut . Ini adalah cara yang tepat untuk membuat marah pengembang. Lagi pula, ia memiliki semua yang ada di komponen. Dan komponen-komponen yang ditampilkan banyak di mana, dan tidak tahu (dan tidak boleh tahu) apa-apa tentang aplikasi. Adalah naif untuk percaya bahwa komponen apa pun akan selalu ada di halaman dalam satu salinan, yang berarti bahwa pengidentifikasi tidak dapat dijahit ke dalam komponen itu sendiri. Tetapi pada level aplikasi, hanya ada penggunaan komponen LegoSidebar. Dan melempar pengidentifikasi melalui beberapa tingkat komponen bersarang juga merupakan peluang.

Seperti yang Anda lihat, satu opsi lebih buruk daripada yang lain - baik pengembang atau penguji menderita. Selain itu, sebagai suatu peraturan, bias terhadap yang terakhir. Karena mereka memasuki bisnis sebagai aturan, ketika yang pertama telah menyelesaikan pengembangan fitur ini, dan mereka memotong yang lain dengan kekuatan dan utama.


Mari kita lihat bagaimana perancang tata letak dari Yandex menangani tata letak blok sederhana ini (saya harus membuang 90% sampah sehingga esensinya terlihat):


 <div class="desk-notif-card"> <div class="desk-notif-card__card"> <div class="desk-notif-card__domik-user usermenu-link"> <a class="home-link usermenu-link__control" href="https://passport.yandex.ru"> <span class="username desk-notif-card__user-name">admin</span> </a> <!-- -  --> </div> </div> </div> <!-- -  --> 

Berkat BEM, elemen yang kami butuhkan memiliki informasi dalam nama kelas tentang konteks satu tingkat ke atas (semacam nama pengguna di beberapa kartu). Tetapi dapatkah Anda yakin bahwa kartu semacam itu akan selalu ada di halaman? Asumsi yang berani. Jadi, sekali lagi, Anda harus memilih di antara dua bangku.


Oh pilihan yang sulit


Dan di sini adalah contoh lain dengan bidang pencarian di mana pengembang dipaksa untuk meletakkan pengenal. Yah, dia mengatakan:


 <input class="input__control input__input" id="text" name="text" /> 

Apakah pengembangnya buruk? Tidak, arsitektur buruk yang tidak membantu menghasilkan pengidentifikasi unik secara global.


Statistik


Bayangkan diri Anda sebagai seorang analis. Anda perlu memahami mengapa pengguna sering mengklik untuk membuka menu akun di bilah samping Yandex : berdasarkan nama pengguna atau dengan gambar profil.


Dasar klik pada wajah


Anda memerlukan informasi sekarang, sehingga Anda hanya memiliki satu bangku - bekerja dengan statistik yang sudah dikumpulkan. Bahkan jika pengembang memastikan bahwa semua klik pada semua halaman sudah direkam sambil mempertahankan seluruh hierarki elemen pada saat klik, Anda masih tidak dapat membuat pemilih yang tepat untuk menyaring klik yang diperlukan. Dan bahkan jika Anda meminta pengembang untuk melakukan ini, dia juga cenderung membuat kesalahan di suatu tempat. Apalagi jika tata letak telah berubah seiring waktu.


Artinya, Anda memerlukan pengidentifikasi unik global untuk elemen yang Anda butuhkan. Apalagi ditempelkan dengan sangat baik di muka. Tetapi karena mayoritas pengembang mengatasi prediksi masa depan yang buruk, biasanya terlihat seperti ini: analis mendatangi pengembang dan meminta pengidentifikasi, dan menerima informasi dalam kasus terbaik dalam sebulan.


Saya layak saya perlu pengenal


Dalam kasus Yandex, buah dari upaya heroik para pengembang terlihat seperti ini:


 <div class="desk-notif-card__domik-user usermenu-link"> <a class="home-link usermenu-link__control" href="https://passport.yandex.ru" data-statlog="notifications.mail.login.usermenu.toggle" > <!-- -  --> </a> <a class="home-link desk-notif-card__user-icon-link usermenu-link__control avatar" href="https://passport.yandex.ru" data-statlog="notifications.mail.login.usermenu.toggle-icon" > <!-- -  --> </a> </div> 

Oh, dan betapa asyiknya setiap elemen untuk selalu memiliki pengidentifikasi ini. Sehingga mereka juga bisa dimengerti manusia. Dan pada saat yang sama mereka stabil, dan tidak berubah dengan perubahan tata letak. Tetapi dengan transmisi manual, kebahagiaan tidak bisa dicapai.


Gaya


Bayangkan diri Anda sebagai desainer tata letak. Anda perlu gaya khususnya nama pengguna dalam kartu di sidebar Yandex. Kami akan melakukan pendekatan pertama ke proyektil, tanpa menggunakan BEM. Inilah komponen Anda:


 const Morda = ()=> <div class="morda"> {/* - */} <LegoSidebar /> </div> 

Dan di sini adalah kumpulan komponen yang didukung oleh orang-orang yang sama sekali berbeda:


 const LegoSidebar = ( { username } )=> <aside className="lego-sidebar"> <LegoCard> <LegoUsername>{ username }</LegoUsername> </LegoCard> </aside> const LegoCard = ( {} , ... children )=> <div className="lego-card"> { ... children } </div> const LegoUsername = ( {} , ... children )=> <div className="lego-username"> { ... children } </div> 

Semuanya memberikan hasil sebagai berikut:


 <body class="morda"> <aside class="lego-sidebar"> <div class="lego-card"> <div class="lego-username">admin</div> </div> <!-- -  --> </aside> </body> 

Pasti butuh valerian


Jika isolasi gaya digunakan, maka Anda tidak punya apa-apa untuk diduduki. Berdiri dan tunggu orang-orang ini menambahkan kelas khusus ke komponen mereka melalui LegoSidebar, ke LegoUsername:


 const LegoSidebar = ( { username , rootClass , cardClass , usernameClass } )=> <aside className={ "lego-sidebar " + rootClass }> <LegoCard rootClass={ cardClass }> <LegoUsername rootClass={ usernameClass}>{ username }</LegoUsername> </LegoCard> </aside> const LegoCard = ( { rootClass } , ... children )=> <div className={ "lego-card " + rootClass }> { ... children } </div> const LegoUsername = ( { rootClass } , ... children )=> <div className={ "lego-username " + rootClass }> { ... children } </div> 

Dan itu baik jika mereka tertanam langsung satu sama lain, dan tidak melalui selusin komponen perantara. Kalau tidak, mereka akan mati di bawah beban mie dari copy-paste.


Mengatasi kesulitan yang dibuat oleh tangan Anda sendiri


Jika isolasi tidak digunakan, maka selamat datang di kursi yang terbuat dari pemilih yang rapuh:


 .morda .lego-sidebar > .lego-card > .lego-username:first-letter { color : inherit; } 

Namun, jika kami memiliki alat yang akan menggunakan nama lokal:


 const Morda = ()=> <div> {/* - */} <Lego_sidebar id="sidebar" /> </div> const Lego_sidebar = ( { username } )=> <aside> <Lego_card id="profile"> <Lego_username id="username">{ username }</Lego_username> </Lego_card> </aside> const Lego_card = ( {} , ... children )=> <div> { ... children } </div> const Lego_username = ( {} , ... children )=> <div> { ... children } </div> 

Saya akan menempelkannya bersama-sama dengan mempertimbangkan komponen yang bersarang, menghasilkan kelas sampai ke akar aplikasi:


 <body class="morda"> <aside class="lego_sidebar morda_sidebar"> <div class="lego_card lego_sidebar_profile morda_sidebar_profile"> <div class="lego_username lego_sidebar_username morda_sidebar_username">admin</div> </div> <!-- -  --> </aside> </body> 

Kemudian kita dapat menyesuaikan dgn mode elemen apa pun , tidak peduli seberapa dalam mungkin:


 .morda_sidebar_username:first-letter { color : inherit; } 

Tidak, ini fantastis. Ini tidak terjadi.


Setelah 5 tahun, kode hipster 99% hanya dapat dibuang


Transfer Barang


Bayangkan diri Anda sebagai pengembang perpustakaan rendering. Algoritme reaktif berkinerja tinggi menggunakan VirtualDOM, IncrementalDOM, Batching DOM, dan Apa pun DOM lainnya memungkinkan Anda menghasilkan DOM jenis ini untuk papan scrum hanya dalam beberapa detik:


 <div class="dashboard"> <div class="column-todo"> <div class="task"> <!--  html --> </div> <!--    --> </div> <div class="column-wip"> </div> <div class="column-done"> </div> </div> 

Dari kondisi seperti ini:


 { todo : [ { /*   */ }, /*   */ ] , wip : [] , done : [] , } 

Dan ini adalah nasib buruk: pengguna mulai menyeret dan menjatuhkan tugas bolak-balik dan mengharapkan ini terjadi dengan cepat. Tampaknya Anda hanya perlu mengambil elemen DOM dari tugas dan memindahkannya ke tempat lain di DOM-e. Tetapi Anda harus bekerja secara manual dengan DOM dan memastikan bahwa di semua tempat tugas selalu dirender ke dalam pohon DOM yang persis sama, yang sering kali tidak terjadi - biasanya ada perbedaan kecil. Singkatnya, mengubah DOM secara manual seperti duduk di atas sepatu roda: satu gerakan yang tidak disengaja dan tidak ada yang akan menyelamatkan Anda dari gravitasi. Penting untuk menjelaskan sistem rendering sehingga mengerti di mana tugas ditransfer, dan di mana satu dihapus dan yang lainnya ditambahkan.


Kesalahan mentransfer identitas ke tubuh yang salah


Untuk mengatasi masalah ini, perlu melengkapi pandangan dengan pengidentifikasi. Jika pengidentifikasi cocok, maka tampilan yang diberikan dapat dengan mudah dipindahkan ke lokasi baru. Jika mereka tidak cocok, maka ini adalah entitas yang berbeda dan Anda perlu menghancurkan satu dan membuat yang lain. Penting bahwa pengidentifikasi tidak diulangi, dan tidak dapat terjadi secara kebetulan.


Saat Anda mentransfer elemen dalam elemen DOM induk yang sama, atribut kunci dari React , parameter ngForTrackBy dari Angular, dan hal-hal serupa dalam kerangka kerja lain dapat membantu Anda. Tetapi ini adalah keputusan yang terlalu pribadi. Sebaiknya pindahkan tugas ke kolom lain, dan semua optimisasi ini berhenti bekerja.


Tetapi jika setiap elemen DOM memiliki pengidentifikasi unik secara global, terlepas dari di mana elemen ini diberikan, maka menggunakan getElementById akan dengan cepat menggunakan kembali pohon DOM yang ada saat memindahkan entitas dari satu tempat ke tempat lain. Tidak seperti kruk untuk daftar render yang disebutkan di atas, pengidentifikasi global menyelesaikan masalah secara sistematis dan tidak akan pecah bahkan jika pengelompokan atau permainan lain muncul di kolom:


 <div id="/dashboard"> <div id="/dashboard/column-todo"> <div id="/dashboard/todo/priority=critical"> <div id="/dashboard/task=y43uy4t6"> <!--  html --> </div> <!--    --> </div> <!--     --> </div> <div id="/dashboard/column-wip"> <div id="/dashboard/wip/assignee=jin"></div> <!--     --> </div> <div id="/dashboard/column-done"> <div id="/dashboard/done/release=0.9.9"></div> <!--     --> </div> </div> 

Pembicara yang dikelompokkan


Semantik


Bayangkan diri Anda sebagai desainer tata letak. Dan Anda perlu menambahkan div di sana. Disajikan? Sekarang bunuh diri. Anda sudah dirusak oleh html.


Bahkan, Anda tidak perlu menambahkan div , tetapi satu blok untuk nama kartu. title - nama blok ini, mencerminkan semantiknya di tempat penggunaan. div adalah jenis blok yang mencerminkan penampilan dan perilakunya, di mana pun ia digunakan. Jika kita mengeset pada TypeScript, maka itu akan dinyatakan seperti ini:


 const Title : DIV 

Kami dapat secara instan membuat instance dari jenis:


 const Title : DIV = new DIV({ children : [ taskName ] }) 

Dan biarkan skrip waktu mencetak jenis secara otomatis:


 const Title = new DIV({ children : [ taskName ] }) 

Nah, di sini, bahkan HTML tidak jauh:


 const Title = <div>{ taskName }</div> 

Perhatikan bahwa Title bukan hanya nama variabel acak yang digunakan dan dibuang. Ini adalah semantik primer dari elemen ini. Dan agar tidak kehilangan itu, itu harus tercermin sebagai akibat dari:


 const Title = <div id="title">{ taskName }</div> 

Dan lagi kita menyingkirkan tautologi:


 <div id="title">{ taskName }</div> 

Tambahkan elemen yang tersisa:


 <div id="task"> <div id="title">{ taskName }</div> <div id="deadline">{ taskDue }</div> <div id="description">{ taskDescription }</div> </div> 

Perhatikan bahwa selain judul kartu tugas, ada banyak tajuk lainnya, termasuk tajuk kartu tugas lainnya:


 <div id="/dashboar/column-todo"> <div id="/dashboard/column-todo/title">To Do</div> <div id="/dashboard/task=fh5yfp6e"> <div id="/dashboard/task=fh5yfp6e/title">{ taskName }</div> <div id="/dashboard/task=fh5yfp6e/deadline">{ taskDue }</div> <div id="/dashboard/task=fh5yfp6e/description">{ taskDescription }</div> </div> <div id="/dashboard/task=fhty50or"> <div id="/dashboard/task=fhty50or/title">{ taskName }</div> <div id="/dashboard/task=fhty50or/deadline">{ taskDue }</div> <div id="/dashboard/task=fhty50or/description">{ taskDescription }</div> </div> </div> 

Dengan demikian, untuk setiap elemen pengidentifikasi yang dapat dibaca manusia dibentuk yang secara akurat mencerminkan semantiknya dan oleh karena itu unik secara global.


Harap dicatat bahwa semantik ditentukan oleh keanggotaan, bukan lokasi. Meskipun kartu tugas /dashboard/task=fh5yfp6e terletak di kolom /dashboard/todo , kartu tersebut berada di /dashboard . Dialah yang menciptakannya. Dia mengaturnya. Dia memberinya nama dan memastikan keunikan identitasnya. Dia sepenuhnya mengendalikannya. Dia akan menghancurkannya.


Ketahui siapa ayahmu


Tetapi penggunaan "tag html yang benar" bukan semantik, melainkan tipifikasi:


 <section id="/dashboard/column-todo"> <h4 id="/dashboard/column-todo/title">To Do</h4> <figure id="/dashboard/task=fh5yfp6e"> <h5 id="/dashboard/task=fh5yfp6e/title">{ taskName }</h5> <time id="/dashboard/task=fh5yfp6e/created">{ taskCreated }</time> <time id="/dashboard/task=fh5yfp6e/deadline">{ taskDue }</time> <div id="/dashboard/task=fh5yfp6e/description">{ taskDescription }</div> </figure> </section> 

Perhatikan dua tag time dengan semantik yang sama sekali berbeda.


Lokalisasi


Bayangkan diri Anda sebagai penerjemah. Anda memiliki tugas yang sangat sederhana - untuk menerjemahkan satu baris teks dari bahasa Inggris ke bahasa Rusia. Anda mendapat string "Selesai". Jika tindakan ini, maka perlu diterjemahkan sebagai "Selesai", dan jika negara, maka sebagai "Selesai", tetapi jika ini adalah keadaan tugas, maka "Selesai". Tanpa informasi tentang konteks penggunaan, mustahil untuk menerjemahkan teks dengan benar. Dan di sini pengembang lagi memiliki dua toko:


  1. Berikan teks dengan komentar dengan informasi konteks. Dan komentar terlalu malas untuk ditulis. Dan seberapa lengkap informasi yang dibutuhkan tidak jelas. Dan lebih banyak kode sudah diperoleh daripada saat menerima teks dengan kunci.
  2. Menerima teks dengan kunci, setelah membaca yang Anda dapat memahami konteks penggunaan. Ditetapkan secara manual, itu tidak menjamin kelengkapan informasi, tetapi setidaknya itu akan unik.

Lagi-lagi pilihan dua kejahatan


Tetapi bagaimana jika kita tidak ingin bagaimana pun duduk, tetapi ingin berdiri dengan bangga atas dasar yang kuat dari praktik terbaik? Maka kita perlu menggunakan kombinasi nama tipe (komponen, template), nama lokal elemen dalam tipe ini dan nama propertinya sebagai kunci. Untuk teks "Selesai" sebagai nama kolom, kunci ini adalah github_issues_dashboard:column-done:title . Dan untuk teks "Selesai" pada tombol penyelesaian tugas di kartu tugas, pengenal sudah akan menjadi github_issues_task-card:button-done:label ). Ini, tentu saja, bukan pengidentifikasi yang kita bicarakan sebelumnya, tetapi kunci-kunci ini dibentuk dari nama yang sama yang secara eksplisit atau implisit kita berikan kepada elemen-elemen penyusunnya. Jika kita menamainya secara eksplisit, maka kita memiliki kesempatan untuk mengotomatiskan pembuatan berbagai kunci dan pengidentifikasi. Tetapi jika secara implisit, maka Anda harus mengatur kunci dan pengidentifikasi ini secara manual dan berharap kekacauan dengan nama entitas yang sama di tempat yang berbeda dengan cara yang berbeda tidak pecah.


Debugging


Bayangkan diri Anda sebagai pengembang aplikasi. Laporan bug datang kepada Anda:


   !  !   ,   : Uncaught TypeError: f is not a function at <Button> at <Panel> at <App> 

"Ya, f terkenal itu dari beberapa tombol, pada beberapa panel," ahli sofa itu akan berkata, "Semuanya jelas."


Di sini dan si bodoh


Atau tidak? Dan jika itu hanya satu pengidentifikasi unik:


 /morda/sidebar/close 

- Ya, tombol tutup bilah samping rusak. VasyaPas, ini untukmu, mereka memindahkan gulungannya.


Vasya duduk untuk lampiran, mengarahkan pengidentifikasi yang diterima ke konsol pengembangan, dan kemudian ia menerima instance komponen, di mana segera jelas bahwa seseorang yang pintar melewati garis ke tombol sebagai penangan klik:


Ini bukan HTML.


Baik bahwa setiap komponen memiliki pengidentifikasi. Dan dengan pengidentifikasi ini, komponen ini mudah didapat , tanpa menari di sekitar debugger. Benar, kami membutuhkan alat yang memungkinkan Anda menemukan komponen dengan pengidentifikasi. Tetapi bagaimana jika pengenal itu sendiri adalah kode program untuk mendapatkan komponen?


 <button id="Components['/morda/sidebar/close']">X</button> 

Kemudian kode ini dapat disalin langsung ke konsol untuk akses cepat ke keadaan komponen, tidak peduli berapa kali kita memuat ulang halaman dan mengubah kode.


Apa yang harus dilakukan


Jika Anda menggunakan $ mol, maka Anda tidak perlu melakukan apa pun - cukup duduk dan dapatkan pijatan getaran secara penuh:


 $ya_morda $mol_view sub / <= Sidebar $ya_lego_sidebar $ya_lego_sidebar $mol_view sub / <= Profile $ya_lego_card sub / <= Username $ya_lego_username sub / <= username \ $ya_lego_card $mol_view $ya_lego_username $mol_view 

Seorang programmer tidak dapat secara sintaksis gagal memberikan komponen nama yang unik. DOM berikut dihasilkan dari deskripsi komponen ini:


 <body id="$ya_morda.Root(0)" ya_morda mol_view > <ya_lego_sidebar id="$ya_morda.Root(0).Sidebar()" ya_lego_sidebar mol_view ya_morda_sidebar > <ya_lego_card id="$ya_morda.Root(0).Sidebar().Profile()" ya_lego_card mol_view ya_lego_sidebar_profile ya_morda_sidebar_profile > <ya_lego_username id="$ya_morda.Root(0).Sidebar().Username()" ya_lego_username mol_view ya_lego_sidebar_username ya_morda_sidebar_username > admin </ya_lego_username> </ya_lego_card> </ya_lego_sidebar> </body> 

Kode dalam pengidentifikasi tidak hanya unik secara global, tetapi juga merupakan API yang melaluinya Anda dapat mengakses komponen apa pun. Nah, stektrays hanyalah dongeng:


 Uncaught (in promise) Error: Test error at $mol_state_local.value("mol-todos-85").calculate at $mol_state_local.value("mol-todos-85").pull at $mol_state_local.value("mol-todos-85").update at $mol_state_local.value("mol-todos-85").get at $mol_app_todomvc.Root(0).task at $mol_app_todomvc.Root(0).task_title at $mol_app_todomvc.Root(0).task_title(85).calculate at $mol_app_todomvc.Root(0).task_title(85).pull at $mol_app_todomvc.Root(0).task_title(85).update at $mol_app_todomvc.Root(0).task_title(85).get at $mol_app_todomvc.Root(0).Task_row(85).title at $mol_app_todomvc.Root(0).Task_row(85).Title().value at $mol_app_todomvc.Root(0).Task_row(85).Title().event_change 

Bukan mereka yang ingin membuat dunia menjadi tempat yang lebih baik


Jika Anda terpikat pada Bereaksi, Anda dapat mentransfer ke transformator JSX khusus untuk menghasilkan pengidentifikasi unik global dengan nama lokal elemen yang disematkan dalam komponen. Anda dapat melakukan hal yang sama dengan generasi kelas untuk styling. Untuk contoh dengan dasbor, templat terlihat seperti ini:


 const Dashboard = ()=> ( <div> <Column id="/column-todo" title="To Do"> <Task id="/task=fh5yfp6e" title="foobar" deadline="yesterday" content="Do it fast!" /> </Column> <Column id="/column-wip" title="WIP" /> <Column id="/column-done" title="Done" /> </div> ) const Column = ( { title } , ... tasks )=> ( <div> <div id="/title">{ title }</div> { tasks } </div> ) const Task = ({ title , deadline , description })=> ( <div> <div id="/title">{ title }</div> <div id="/deadline">{ deadline }</div> <div id="/description">{ description }</div> </div> ) const App = ()=> <Dashboard id="/dashboard" /> 

Pada menghasilkan output:


 <div id="/dashboar"> <div id="/dashboar/column-todo"> <div id="/dashboard/column-todo/title">To Do</div> <div id="/dashboard/task=fh5yfp6e"> <div id="/dashboard/task=fh5yfp6e/title">foobar</div> <div id="/dashboard/task=fh5yfp6e/deadline">yesterday</div> <div id="/dashboard/task=fh5yfp6e/description">Do it fast!</div> </div> </div> <div id="/dashboar/wip"> <div id="/dashboard/column-wip/title">WIP</div> </div> <div id="/dashboar/done"> <div id="/dashboard/column-done/title">Done</div> </div> </div> 

Oh berapa banyak copy-paste


Jika Anda menjadi sandera bagi kerangka kerja lainnya, maka buatlah untuk penulis masalah untuk menambahkan kemampuan opsional untuk menghasilkan pengidentifikasi dan kelas. Atau setidaknya untuk menambahkan API di mana fitur tersebut dapat diimplementasikan secara mandiri.


Meringkas, saya mengingatkan Anda mengapa Anda perlu memberikan nama unik untuk semua elemen:


  • Kesederhanaan dan stabilitas tes E2E.
  • Kemudahan mengumpulkan statistik penggunaan aplikasi dan analisisnya.
  • Penataan mudah.
  • Efisiensi rendering.
  • Semantik yang akurat dan komprehensif.
  • Kemudahan lokalisasi.
  • Kemudahan debugging.

Source: https://habr.com/ru/post/id461395/


All Articles