Arsitektur frontend tingkat atas. Kuliah Yandex

Memilih arsitektur yang tepat adalah bagian penting dari membangun layanan front-end. Pengembang Anna Karpelevich memberi tahu para siswa di School of Interface Development apa itu arsitektur, apa fungsinya, dan masalah apa yang dipecahkannya. Dari kuliah Anda dapat belajar tentang pendekatan arsitektur paling populer di front-end: Model-View- * dan Flux.


- Selamat sore. Nama saya Anya Karpelevich. Hari ini kita akan berbicara tentang arsitektur front-end top-level.

Saya bekerja di Yandex.Direct. Kami membuat antarmuka untuk pengiklan. Mereka memposting iklan, menyesuaikannya. Ini adalah sistem yang sangat kompleks, menarik, ia memiliki banyak komponen yang saling berhubungan, mereka tumbuh menjadi satu sama lain, mereka memiliki kesamaan dan fungsi mereka sendiri. "Celana berubah menjadi celana pendek yang elegan." Semua ini harus dikontrol dengan sangat hati-hati. Dan arsitektur dalam aplikasi kita sangat kompleks. Ini adalah salah satu alasan mengapa saya memberikan kuliah ini hari ini. Saya sangat suka topik ini.

Apa itu arsitektur? Faktanya adalah bahwa mungkin tidak ada jawaban untuk pertanyaan ini. Atau ada, tetapi masing-masing memiliki sendiri. Ini adalah topik yang sangat kontroversial. Itu menyebabkan banyak kontroversi, banyak holivar. Dan banyak hal yang akan saya bicarakan hari ini adalah pendapat saya. Sebagian didukung oleh kelompok kerja saya, sebagian tidak terlalu banyak. Dan semua orang, ketika dia menulis arsitektur aplikasinya, memutuskan sendiri bagaimana dan apa yang harus dilakukan.

Itulah sebabnya arsitektur adalah salah satu tempat paling kreatif dalam karya seorang programmer. Dan oleh karena itu, presentasi kami hari ini juga akan dimulai dengan kreativitas.



Mari kita lihat gambar kiri. Saya akan sangat senang jika seseorang mengenali bangunan yang ditampilkan di sana. Ini adalah gereja Saint-Sulpice di Paris. Perhatikan menara, demi mereka gereja ini diletakkan di sini. Saya harap mereka berbeda. Mereka sangat berbeda, dan ada alasan menarik untuk ini. Di antara mereka perbedaan 130 tahun. Kemudian menara kiri dihancurkan dan dibangun kembali selama perang Perancis-Prusia.

Kenapa dia ada di sini? Lihatlah gambar ini. Menara memiliki arsitektur yang sama, dan seluruh lingkungan, sketsa, perlengkapan, struktur melengkung berbeda. Kenapa begitu Karena tujuan dari menara ini adalah sama. Tidak satu pun dari mereka, misalnya, menara lonceng. Ini hanya menara. Ada sesuatu yang tersimpan di dalamnya, dan yang lainnya berbeda. Mengapa Karena arsitektur menara ini adalah sama. Keduanya memiliki lemari besi, hanya satu jendela, dan itu adalah lanset. Jendela-jendelanya kira-kira sama tingginya. Dan idenya adalah bahwa arsitektur, baik bangunan maupun aplikasi, adalah struktur pendukung. Ini bukan sketsa, bukan flicker, bukan implementasi. Inilah yang menjadi intinya. Dan fondasi ini, sebagai suatu peraturan, tergantung pada lingkungan, pada tanah, ketika sampai pada bangunan, pada tujuan yang ditetapkan arsitek untuk dirinya sendiri, tetapi hampir tidak pernah bergantung pada penyempurnaan desain.

Contoh bangunan untuk tema arsitektur cukup jelas. Namun gambar yang tepat lebih menarik. "Arsitektur adalah musik yang mati rasa." "Architektur ist gefrorene Musik," kata Johann Wolfgang Goethe pada abad ke-18. Goethe kemungkinan besar tidak tahu apa-apa tentang arsitektur bangunan, dia penyair. Dan dia dijamin tidak tahu apa-apa tentang arsitektur aplikasi. Namun dia mengungkapkan ide yang sangat berharga dan menarik.

Musik ada dalam dinamika. Ini bukan sesuatu yang statis. Ini sebuah proses. Dan begitu saja, aplikasi adalah suatu proses. Dia memiliki momen peluncuran, dia memiliki momen pengembangan, ketika kita melakukan sesuatu dengannya, bekerja. Dan dia akhirnya memiliki saat penyelesaian. Arsitektur aplikasi adalah irisannya pada waktu tertentu. Setiap saat, aplikasi kita, sebagai tema musik, harus jelas, jelas, dapat dimengerti, dapat diprediksi, dll. Jika tidak, semuanya akan berantakan.

Dengan pengantar kreatif ini, kami mengakhiri, beralih ke hal-hal yang lebih duniawi, lebih dekat dengan praktik membangun aplikasi.

Apa itu arsitektur dan mengapa itu dibutuhkan?



Pertama, kita memiliki pengaturan sejumlah besar kode, sesuatu yang kita temukan di Direct, dan tidak hanya di Direct, setiap saat. Ada begitu banyak kode sehingga Anda bisa tersesat di dalamnya. Kami tidak ingin tersesat dalam kode.

Kedua, duplikasi fungsi. Ini juga merupakan masalah abadi yang akan selalu Anda temui, dan hari ini topik duplikasi ini akan menembus garis merah melalui seluruh kuliah. Fungsionalitas yang sama mungkin kita butuhkan di beberapa tempat pada antarmuka. Jika diperlukan di beberapa tempat, maka harus secara fisik kode yang sama yang digunakan di beberapa tempat, bukan salinan. Mengapa Kami akan membicarakan ini lebih lanjut. Tetapi arsitektur seharusnya membantu kita menghindari copy-paste.

Ketiga adalah dukungan. Sangat jelas bahwa jika kita memiliki aplikasi, maka kita perlu mendukungnya, dan disarankan agar semua sumber daya tim tidak terbuang untuk hal ini.

Ubah komposisi tim. Itu juga hal yang sering kita temui dalam kehidupan nyata daripada yang kita inginkan. Seseorang datang, seseorang pergi, dan jika seseorang menghabiskan enam bulan untuk memasukkan kode, ini buruk. Jika pengetahuan tentang kode disimpan hanya dalam satu kepala, dan itu akan mengirimkan pengetahuan ini selama enam bulan jika meninggalkan, ini bahkan lebih buruk. Secara umum, di sini arsitektur juga membantu kita untuk membuat semua ini lebih mudah dipahami dan untuk mempertahankan berbagi pengetahuan.

Menambah dan memperluas fungsionalitas. Juga hal yang cukup jelas. Manajer datang berlari kepada kami dan mengatakan bahwa ini sangat dibutuhkan. Dan jika untuk melakukan ini dengan segera, Anda harus menghabiskan banyak waktu dan usaha, maka ini adalah solusi arsitektur yang buruk. Dan kita membutuhkan yang baik.

Dan akhirnya, kesalahan. Semakin mudah dipahami, dapat diprediksi arsitektur kita, semakin mudah untuk mencari kesalahan, semakin sedikit bug.

Bagaimana semua ini bisa disebut? Semua ini bisa disebut - masalah sistem yang kompleks. Aplikasi adalah sistem yang kompleks, arsitektur membantu kita memecahkan masalah.



Singkatnya, entah bagaimana. Ini adalah gambar mie di sebelah kanan saya, dan inilah yang terjadi jika Anda tidak mengikuti arsitektur, jika Anda tidak membuatnya, memikirkannya dan mendesainnya. Dan gambar kedua adalah apa yang terjadi jika arsitektur setidaknya dipikirkan dengan baik. Ini bukan Saint-Sulpice, tetapi setidaknya seorang desainer anak-anak, ia berdiri kokoh dan tidak berantakan. Hari ini kami akan memainkan banyak konstruktor juga.



Secara formal tentang semua ini. Arsitektur adalah cara untuk memecahkan masalah sistem yang kompleks dengan abstraksi implementasi dari antarmuka dan diferensiasi kekuatan antara blok kode. Selanjutnya kami akan menganalisis kalimat panjang ini secara rinci.

Apa saja fitur arsitektur aplikasi sebagai bidang pengetahuan? Dia memiliki area spesifik tempat kami bekerja. Artinya, itu bukan sesuatu yang abstrak, itu adalah hal yang sangat spesifik. Inilah tugasnya, kita memilih arsitektur untuk itu, dan tidak begitu, oooh, pendekatan arsitektur yang menarik, kita harus coba. Jadi tidak. Anda dapat mencoba sesuatu yang kecil, tetapi untuk proyek serius, arsitektur dipilih, kadang-kadang dibuat untuk proyek tertentu.

Sejarah masalah, ketika, secara umum, ide ini muncul bahwa arsitektur harus dilakukan. Ini, harus saya katakan, pada suatu waktu ide yang sangat luar biasa diungkapkan pada tahun 1968 oleh Edsger Dijkstra, seorang programmer yang hebat. Dia mungkin lebih dikenal sebagai penulis algoritma Dijkstra, pencarian jalur terpendek dalam grafik. Tapi dia punya banyak ide terobosan untuk masanya. Dan salah satunya adalah artikel, maka saya akan memberi Anda referensi ke materi, Anda bisa membaca, hanya ada dua halaman, esai singkat. Kedengarannya seperti "Operator GOTO dianggap berbahaya", dalam terjemahan "Operator GOTO - operator transisi tanpa syarat - jahat". Itu adalah pemikiran pertama yang secara resmi mengatakan bahwa kita perlu menulis arsitektur, bukan mie.

Di tahun 70-an, ide ini sudah dikembangkan oleh Dijkstra bekerja sama dengan Parnassus, dan sendiri, secara individu. Buku rinci pertama tentang arsitektur aplikasi secara umum ditulis pada tahun 1996 oleh Mary Shaw dan David Garlan. Setelah itu, pada kenyataannya, buku-buku rinci tentang arsitektur perangkat lunak tidak ditulis secara tepat karena ruang lingkupnya, sehingga setiap bidang pengetahuan memiliki pendekatan arsitekturnya sendiri, di suatu tempat, di tempat lain yang lebih populer, sesuatu, umumnya tidak berlaku di beberapa tempat. Dan karena arsitektur adalah proses kreatif, Anda tidak akan menemukan buku khusus tentang cara menulis arsitektur. Mungkin setelah 1996 tidak ada yang secara khusus merinci tentang hal ini.

Apa persyaratan untuk arsitektur proyek sekarang. Pertama, dan yang paling penting, apa yang dibutuhkan darinya, pada kenyataannya, adalah diperpanjang, karena jika proyek Anda tidak berkembang, itu sudah mati.

Menggunakan kembali kode. Ini tentang copy-paste. Jika Anda memiliki dua blok yang digunakan di dua tempat yang berbeda, Anda memerlukan fungsionalitas yang sama, maka Anda perlu menggunakan kembali kode yang sama, dan arsitekturnya harus sedemikian rupa sehingga setiap potongan kode dapat diambil dan digunakan kembali segera setelah diperlukan .

Pemisahan otoritas antara modul kode. Kita akan membicarakan ini hari ini secara lebih terperinci, mengapa ini perlu. Idenya adalah ini: setiap modul, setiap blok, setiap bagian kode harus melakukan satu tindakan spesifik, membawa tepat satu fungsi. Dan fungsi ini harus ditempatkan dalam judul metode ini, kelas, apa pun itu, modul. Satu modul - satu fungsi.

Dan akhirnya, kualitas aplikasi. Ada banyak hal yang ingin saya lakukan - baik keandalan maupun kompatibilitas. Pada kenyataannya, sekali lagi, dipilih untuk tugas tersebut. Dibutuhkan kompatibilitas di suatu tempat agar tidak ada yang bergerak. Diperlukan keandalan di suatu tempat sehingga, Tuhan melarang, kata sandi, kode pin kartu atau CVV tidak akan bocor di mana pun. Di suatu tempat Anda membutuhkannya agar bebas masalah jika itu adalah satelit atau sesuatu yang lain. Secara umum, pilih beberapa saja. Semakin Anda ingin mendukung, semakin banyak kompleksitas yang mungkin Anda temui dalam arsitektur.

Selanjutnya kami akan berbicara dengan Anda tentang beberapa definisi, hanya hal-hal ensiklopedis seperti itu. Mengapa ini penting? Karena terminologi dalam arsitektur sangat penting, dan kami perlu berbicara bahasa yang sama dengan Anda. Definisi untuk sebagian besar diambil dari paradigma pemrograman yang disebut OOP. Tetapi pada kenyataannya, mereka telah tumbuh ke dalam paradigma lain, dengan istilah "kelas, objek, antarmuka" mereka beroperasi tidak hanya dalam kerangka kerja OOP. Namun, definisi dan pemahaman ini diambil justru dari dunia OOP.



Yang paling sederhana adalah kelas. Apa itu kelas? Ini adalah template, ini adalah sampel. Sebagai contoh, kelas Snake adalah kelas Snake. Kami telah mendefinisikan tiga bidang pribadi dengannya, yaitu, bidang yang tidak dapat diakses oleh siapa pun kecuali metode kelas itu sendiri - jumlah tujuan, jumlah ekor, dan panjang burung beo. Kami menentukan konstruktor di mana kami menempatkan kepala, ekor, dan panjang yang sama ini di burung beo. Dapatkan kelas Snake. Semuanya sederhana.



Kita melangkah lebih jauh. Obyek. Dan objek adalah turunan dari struktur tertentu. Selain itu, sekali lagi dalam OOP klasik, tersirat bahwa suatu objek adalah objek kelas. Di dunia modern, dalam JavaScript, yang tidak selalu merupakan bahasa OOP, dan bahkan sekarang tidak selalu dan di mana-mana OOP, kita tahu bahwa bisa ada objek abstrak. Artinya, kita dapat membuat objek, literal, yang tidak akan menjadi objek kelas. Tapi di sini adalah contoh bagaimana kita membuat objek dari kelas Snake. Di sini kita memiliki ular dua sisi dengan panjang 38 nuri, - seekor ular boa.



Modul Modul adalah unit semantik. Ini tidak selalu kelas. Itu bisa berupa sekumpulan kelas, sekumpulan objek, sekumpulan metode yang tidak digabungkan ke dalam kelas. Biasanya, Anda dapat mengasumsikan bahwa modul adalah apa yang Anda tulis ke satu file. Tetapi, pada prinsipnya, modul adalah folder di mana mereka berada, misalnya, file dan tes untuk modul ini juga merupakan modul. Yang penting di sini adalah bahwa modul adalah apa yang Anda sebut modul, apa yang Anda anggap sebagai unit semantik. Dalam hal ini, modulnya adalah tentang bagaimana kita makan ular. Hasil dari modul ini adalah metode terakhir, eatSnake, saat kami makan ular. Saya tidak tahu mengapa kita makan ular, tetapi kita bisa melakukannya, karena kita menulis modul ini seperti itu.



Itu sepele, maka hal yang sedikit lebih menarik akan dimulai. Antarmuka kelas. Antarmuka kelas adalah, lebih sederhana, metode publiknya, apa yang menonjol, apa yang bisa kita dapatkan dari objek kelas ini dari objek dari luar. Kelas ini mengimplementasikan antarmuka getSnakeLength. Dia bisa mengembalikan panjang ular kepada kita. Harap dicatat bahwa tidak ada akses eksternal ke bidang pribadi. Akses dari luar hanya untuk metode publik getSnakeLength.



Dan kemudian hal yang sangat menarik. Kami berdebat lama tentang bagaimana menyebut hal ini, karena saya menciptakan istilah "antarmuka abstrak" ketika saya membuat kuliah ini. Dan jujur, saya belum pernah melihat definisi normal dari pendekatan dan metode ini. Namun, banyak bahasa pemrograman memungkinkan Anda untuk membuat antarmuka abstrak, dan menyebutnya, segera setelah bukan kelas abstrak, dan antarmuka abstrak juga, hanya antarmuka. Ternyata homonim dengan antarmuka kelas. Idenya adalah bahwa antarmuka abstrak adalah seperangkat metode yang melakukan sesuatu. Ketika kita membuat kelas, kita beralih dari pertanyaan "apa ini?" Ini adalah ular dan dia tahu bagaimana melakukan sesuatu, atau tidak. Dia hanya bisa memberikan panjangnya.

Dan ketika kita membuat antarmuka, kita beralih dari apa yang dia lakukan, apa yang seharusnya bisa dia lakukan. Dan ini terbukti menjadi cara yang sangat ampuh untuk memperluas kelas. Kita dapat mengaitkan kelas ke beberapa kelas, memperluasnya dengan bantuan antarmuka. Sebagai contoh, kerangka kerja I-BEM dapat melakukan hal seperti itu, sebuah cerita dengan antarmuka abstrak dibangun ke dalam kerangka kerja tersebut. Sayangnya, banyak kerangka kerja tidak tahu caranya, dan masalahnya kuat.

Di sini, sebagai contoh, kami menciptakan antarmuka yang dapat didengar, sesuatu yang bisa terdengar. Dan definisinya adalah metode getNoise kosong abstrak. Kami memperluas ular kami dengan kelas audiable, menerapkan metode getNoise, dan ular kami mendesis. Inspirasi untuk set contoh ini diberikan kepada saya oleh buku indah oleh Eric Freeman dan Pola Desain.

Sekarang kita akan mencoba melihat contoh-contoh ini sedikit lebih spesifik.



Tetapi pertama-tama, mari kita bicara tentang mengapa contoh-contoh ini diperlukan. Dan mereka dibutuhkan di sini untuk slide besar ini. Apa yang ditulis di sini sangat penting sehingga saya bahkan meletakkannya di blok judul kuning. Bisa dikatakan mantra. Ini adalah prinsip yang sangat penting yang harus selalu Anda pikirkan ketika Anda mendesain arsitektur. Kohesi tinggi, kopling rendah - daya rekat kuat, konektivitas lemah. Ada masalah tertentu dengan fakta bahwa kata kohesitas dan penggandaan kata diterjemahkan ke dalam bahasa Rusia, dan seterusnya, dan seterusnya, "keterhubungan" diterjemahkan, kata penggandaan secara khusus diciptakan untuk prinsip ini.

Ini idenya. Blok Anda harus sangat kompak, sangat erat. Mereka harus menerapkan tepat satu fungsi. Dan di antara mereka sendiri, mereka harus terhubung dengan sangat mudah sehingga mereka dapat dengan mudah digabungkan, dirakit, seperti seorang desainer. Dan kemudian arsitektur Anda akan cukup fleksibel dan cukup andal. Dan juga mudah diuji.

Mari kita lihat bagaimana kita dapat mencapai traksi yang kuat dan kopling yang lemah pada poin dari apa yang disebut.



Spesialisasi Setiap blok hanya memecahkan satu masalah. Di sini kami memiliki ilustrasi yang bagus - seorang desainer anak-anak. Kami memiliki setiap blok, atau serangkaian blok. Mereka semua dari bentuk dan ukurannya. Dan jika kita perlu membangun rumah, kita akan mengambil jeruji panjang. Jika kita perlu membuat bola, kita akan mengambil balok pendek. Setiap bilah memiliki fungsinya sendiri. Dan mereka yang memainkan konstruktor tahu: semakin sederhana bentuk potongan, semakin banyak yang dapat Anda buat darinya. Tidak ada yang akan dibangun dari zagogulin tersebut, atau hanya apa yang dijelaskan dalam instruksi yang dibuat. Dan siapa yang membutuhkannya?

Hal yang sama, abstraksi. Ini tentang abstraksi antarmuka dari implementasi. Idenya adalah bahwa antarmuka adalah eksternal, bagaimana kelas kita, blok kita mencuat, bagaimana berinteraksi dengan blok lain seharusnya tidak mempengaruhi implementasi internalnya. Sebaliknya - itu terjadi. Cara lain - tidak pernah. Dalam arsitektur yang bagus. Di sini, sebagai contoh, pembentukan jerawat ini tidak mempengaruhi bentuk balok itu sendiri. Kami memilih secara terpisah bentuk blok dan menempelkan lem di atasnya.



Enkapsulasi. Kelanjutan dari topik sebelumnya. Dalam metode pribadi, yaitu, dari dalam blok kami, kami menyadari arti dari blok kami, implementasi. Dan antarmuka, cara mereka terhubung, ada di depan umum. Artinya, dalam hal ini, semua persilangan ini, tanda hubung dan bentuk itu sendiri adalah implementasi. Dan jerawat adalah antarmuka. Dan arsitektur yang bagus terlihat seperti konstruktor.



Oh, monster yang menakutkan. Ini tentang menggunakan kembali kode. Awalnya, monster ini, pada kenyataannya, adalah untuk menunjukkan contoh arsitektur yang buruk, tetapi perhatikan dengan cermat. Dia cantik. Terlebih lagi, dia jelas senang dengan hidupnya, berjalan dengan penuh semangat di kakinya yang aneh. Mungkin dia bahkan tahu cara terbang, atau, setidaknya, dia memiliki sayap kupu-kupu yang indah.

Apa idenya? Jika Anda memiliki implementasi untuk unta dan implementasi untuk buaya, dan seorang manajer mendatangi Anda dan mengatakan bahwa buaya unta sangat dibutuhkan. Anda tidak menulis buaya unta secara terpisah. Anda mengambil tubuh unta, pisahkan dari seluruh realisasi unta. Ambil kepala buaya, pisahkan dari buaya, dan gunakan kembali baloknya. Mengapa ini perlu?

Kemudian, ketika manajer datang berlari ke Anda lagi dan mengatakan bahwa kami segera melakukan ekspansi ke Amerika Selatan, dan ada buaya, kami perlu mempertahankan bentuk rahang yang tidak teratur, atau di sana, gigi keempat buaya tidak seperti itu, Anda tidak akan meraba-raba seluruh proyek , di mana Anda telah menyalin kepala buaya. Karena Anda mungkin memiliki buaya zebra-bison-lain di dekatnya. Anda cukup mengambil kelas Anda sebagai kepala buaya, membuat ekstensi dari seri kepala buaya, berikan parameternya, itu akan menentukan sendiri giginya yang akan diambil. Dan itu saja. Di satu tempat, dan tidak di semua tempat di mana ia digunakan.

Di sini, keandalan meningkat pada waktu, karena Anda dijamin akan melupakan beberapa kepala yang disalin dalam beberapa proyek yang sangat langka. Secara umum, tidak ada yang salah dengan mayat semacam itu. Kadav yang bagus, bermanfaat.



Sekarang kita akan melihat langsung pada contoh kode buruk. Harap dicatat ini adalah kode semu. Pseudocode agak mirip dengan TypeScript, tetapi masih pseudocode. Jangan mencoba memulainya, itu tidak berhasil. Anda dapat mengulanginya, Anda tidak boleh menjalankan kode ini karena menggunakan konstruksi sintaks yang tidak didukung oleh TypeScript 2.7, tetapi ilustrasinya telah terbukti baik (sekarang ada contoh yang lebih relevan - kira-kira Ed.).

Jadi, kami memiliki Pengguna kelas. Dia memiliki nama dan umur. Semuanya baik-baik saja. Kami memiliki Pengguna dengan nama keluarga, saya minta maaf untuk font perpisahan. Pengguna dengan nama belakang, ia memiliki nama depan, umur dan nama belakang.

printLabel. User. , User User, . User User , , . - , .

, ? , . , . , − , UserWithSurname, , printLabel. ? , , , , . - ? , . , − , . . PrintLabel . ? ? , .

, . , . , , . , if, , . , , .



printLabel, , iPrintLabel , iPhone, . - getText. User, iPrintLabel. , , , - , getText iPrintLabel, , . UserWithSurname, User, Surname getText. printLabel . iPrintLabel getText.

, , , . . , , . , , , , , iPrintLabel, , , , − . printLabel . , .

. , , , front-end, , . , front-end , , .



-? . - back-end. - API, , REST API REST. — , − -. , , - PowerPoint, . .

front-end. Front-end - . - , . , - . . . , -, . , , . .

front-end, , , , , , , .

> - ( Client-server )
> ( Component-based )
> ( Event-driven )
> REST ( Representational state transfer )
> --*( MVC , MVP , MVVM )
> ( Flux )

Ini adalah pendekatan arsitektur. Beberapa dari mereka yang kami sebutkan hari ini. Arsitektur server klien; arsitektur komponen, salah satu variasinya tidak asing lagi bagi Anda dari React, semoga tidak asing. Kejadian, yang anehnya, juga akrab bagi semua orang, didasarkan pada hampir semua sistem operasi untuk komputer pribadi. REST, yang kami sukai di server, dan dua yang terakhir, yang akan kami ketahui secara rinci hari ini, adalah yang paling front-end, yang kami kerjakan adalah model presentasi * dan aliran data searah.

Mari kita mulai dengan MV *. Mengapa asterisk? Sejarah, seperti kata mereka, penuh dengan rasa sakit dan kemarahan. Sekali waktu, kembali ke tahun 80-an, pendekatan arsitektur yang luar biasa dari MVC diciptakan. M - Model, V - View, C - Controller. Pendekatannya sangat nyaman. Diciptakan secara umum untuk aplikasi konsol. Tetapi ketika teknologi web mulai berkembang, ketika mereka semua mulai menggunakannya, ternyata kadang-kadang diperlukan, di sini model MV bagus, tetapi Controller tidak diimplementasikan dengan cara yang benar. Akibatnya, ada begitu banyak variasi yang berbeda dari implementasi Model-View - sesuatu yang pada awalnya menjadi bingung karena semua itu disebut MVC. Karena, jika ada model MV, maka yang ketiga adalah Pengendali, tidak masalah apa yang kami masukkan di sana.

Kemudian ternyata orang menjadi bingung dan memaksudkan hal yang sama sekali berbeda oleh MVC. Sekitar sekarang, tidak lebih dari setahun yang lalu, mereka mulai secara aktif berbagi terminologi ini, dan membuat nama mereka sendiri untuk setiap implementasi dari pendekatan ini. Dengan satu atau lain cara, MV * ini muncul. Saya juga melihat istilah MVW di Internet, di mana W adalah Apapun. Sebenarnya, kami sedang bergerak ke teknologi-MVC.



Bagaimana mereka diatur? Idenya adalah bahwa kita memiliki model yang menyimpan data. Biasanya ada banyak dari mereka. Ada beberapa jenis tampilan yang menunjukkan data ini kepada pengguna. Mereka, sebagai suatu peraturan, juga banyak. Dan komponen ketiga, yang merupakan perantara di antara mereka, menghubungkan data dan tampilan. Di sini pengguna di sudut kanan atas bekerja dengan semua ini.



MVC, cara semuanya dimulai kembali pada tahun 1980, Smalltalk. Tetapi dalam bentuk ini ia ada dalam beberapa kerangka kerja sejauh ini. Tidak dalam beberapa, cukup banyak. Apa idenya? Pengguna bekerja secara langsung dengan tampilan dan pengontrol. Dia memasukkan data ke beberapa bidang dalam tampilan, menekan tombol kirim dan data masuk ke controller. Ini adalah pengiriman formulir. Pengajuan formulir yang jujur ​​seperti itu dengan tombol kirim, saya kenal bagi semua orang sejak lama, saya harap.

Kami melihat. Panah kuning dari pengguna ke controller - ini adalah pengguna mentransfer data ke controller menggunakan tombol kirim. Panah hijau, - kontrol lewat sana. Pengontrol melihat data ini. Mungkin dia entah bagaimana memprosesnya, kehalusan implementasi sudah ada di sini, dan mengirimkannya ke model yang diinginkan. Pengontrol itu sendiri memilih model mana yang akan dikirim. Mengirim panah hijau, mengirim data dengan panah kuning.

Model juga memproses data. Mungkin dia memvalidasi mereka. Mungkin dia menempatkan mereka di pangkalan. Singkatnya, model tahu apa yang harus dilakukan dengan mereka. Sebagai aturan, hasilnya adalah data baru. Misalnya, kita dapat memberi tahu pengguna apakah dia masuk atau tidak, dan model memeriksa kata sandi dengan login. Setelah itu, model mentransfer kontrol ke controller lagi, sehingga controller memilih tampilan mana yang akan ditampilkan. Dan data langsung menuju ke View. Bagaimana ini bisa dilakukan, secara umum, bagaimana model mengirim data ke tampilan?



Sangat sederhana. Jika controller dan model ada di back-end, dan Templating View berada di sisi server. Inilah bagaimana kerangka kerja Ruby on Rails, ASP.NET, Django disusun, secara umum, di mana pun Anda menulis templating sisi-server, dan HTML yang dikumpulkan datang ke klien, dan datanya juga kembali, dengan probabilitas tinggi, inilah pendekatan ini. Apa masalahnya di sini. Dalam satu aplikasi halaman, hal seperti itu tidak dapat dibangun. Kami selalu memiliki data di server, pergi ke server, halaman dimuat ulang. Kedua, sama sekali tidak jelas di mana harus mendorong validasi klien, dan, secara umum, JavaScript klien, AJAX dan semua ini di sini? Karena jika kita menginginkan sesuatu dengan cepat, tidak ada tempat. Ini sama sekali tidak bekerja dalam pendekatan ini, atau berfungsi sehingga tidak bekerja lebih baik.

Baris terakhir di sini, ini adalah kisah yang sangat menarik, berakar, tampaknya, pada tahun 2008. Pertanyaannya adalah: di mana menyimpan logika bisnis - pada model atau di controller? Ada yang mengatakan: "Kami menyimpan logika bisnis di controller, karena nyaman, data yang segera bersih dikirim ke model. Pengontrol akan memvalidasi dirinya sendiri, memeriksa kembali, jika ada, dan mengirim kesalahan. " Ada orang-orang yang mengatakan bahwa "Hasilnya adalah pengendali jelek yang gemuk dan bodoh, pengendali jelek yang bodoh." Mereka ternyata sangat besar. Dan mereka mengatakan bahwa logika bisnis harus dalam model, dan pengontrol harus tipis, ringan, mentransfer data, model itu sendiri diproses. Dan kemudian dalam versi pertama, modelnya, secara umum, ternyata hanyalah sebuah API untuk basis data.

Bagaimana, menurut saya, sungguh? Bahkan, Anda perlu memperhatikan tugas mereka. Jika Anda memiliki koneksi antara tampilan dan model yang selalu satu lawan satu, satu Tampilan adalah satu model, maka akan lebih mudah bagi Anda untuk melakukan logika bisnis dalam pengontrol, dan membuat model bersih sederhana, yang, pada kenyataannya, akan menjadi API ke database. Jika tampilan dan model Anda dapat tumpang tindih, dan satu tampilan tergantung pada banyak model, model tersebut berfungsi dengan banyak tampilan, akan lebih mudah bagi Anda untuk memiliki banyak pengontrol tipis dan melipatgandakannya dalam perkembangan apa pun, Anda tidak peduli berapa banyak yang ada, mereka masih kecil.

Saya harus mengatakan bahwa dunia tampaknya telah memenangkan sudut pandang kedua, dengan logika bisnis dalam model. Artinya, pengendali jelek bodoh yang gemuk ini tampaknya tidak begitu aktif digunakan. Sinyal, Anda dapat menonton apa yang ada di dokumentasi untuk ASP.NET, kerangka kerja kembali pada 2013 logika bisnis yang diusulkan di controller. Dan dalam versi terbaru tahun 2014 - dalam model. Ada momen yang sangat menarik ketika ini berubah.

Apa MVC memiliki masalah. Kami sudah berbicara dengan mereka, tetapi kami akan melakukannya. Menguji karena tidak jelas bagaimana menerapkan validasi klien adalah mungkin, tetapi sulit, AJAX kacau ke samping, Anda perlu melakukan sesuatu. Mereka datang dengan solusi. Solusinya disebut MVP, dan, ya, Anda dapat bertemu MVP dalam kerangka dengan teks bahwa mereka adalah MVC. Misalnya, kerangka Backbone MVP. Tentang dia untuk waktu yang lama dalam dokumentasi di 2011-2012-2013 yang sama ditulis bahwa ini adalah kerangka kerja MVC.



Model-View-Presenter. Rencananya sudah jauh lebih sederhana. Ada beberapa model. Mereka berinteraksi satu sama lain. Mereka memberikan data kepada Presenter, Presenter mentransfernya ke tampilan, menunjukkannya kepada pengguna. Dan kembali. Pengguna mengarahkan sesuatu ke tampilan, mengklik tombol, tampilan Presenter, AJAX mengirim ke model atau memasukkan ke dalam model, dan model AJAX mengirim ke server. Artinya, semuanya sudah jauh lebih sederhana dan linier, tetapi tanpa standarisasi sisi server sudah akan ada kesulitan. Jika Anda menginginkan server, sistem seperti itu akan rumit.



Mari kita bandingkan. Mari kita lihat gambar pertama, di mana kita akan mencoba menerapkan hal yang sangat sederhana - mengirim data dari input ke model. Kami memasukkan sesuatu, mengklik tombol, itu akan muncul dalam model, model akan melakukan sesuatu dengan ini dan memberi tahu kami bahwa sesuatu terjadi. Kami melaju masuk: "nama saya Vasya", klik ok. Jika kita ingin validasi sisi klien, maka itu terjadi di sini, hampir dengan intersepsi, dalam kasus yang sangat parah, memang, dengan mencegat klik melalui event.preventDefault (). Dan di suatu tempat, titik nol di samping melesat validasi klien.

Kemudian kami dengan jujur ​​mengirim data melalui formulir kirim ke controller. Data masuk ke dalam model, model memasukkannya ke dalam dirinya sendiri, proses, penampilan. Memberitahu kami bahwa, well, datanya diterima, Anda benar-benar Vasya. Panah ketiga - kontrol menuju controller, model memberitahu controller itu, tolong tunjukkan label “My name is Vasya”. Pengontrol memilih tampilan yang sesuai, menampilkan label. Dan data "nama saya Vasya", panah keempat, kuning, model diletakkan di sana. Pertanyaannya adalah bagaimana cara menguji ini? Hanya snapshot. Tidak ada jalan lain. Tidak ada yang menulis bahkan tes fungsional.

Opsi kedua, sudah dengan MVP. Kami melaju "nama saya Vasya", klik ok. Panah di bawah nomor satu, hijau, - manajemen pergi ke Presenter. Presenter berkata: tombol ditekan. Presenter terlihat, panah nomor dua, biru, perhatikan ini adalah permintaan data. Dalam MVP klasik, tidak mengirim data dari tampilan ke Presenter, tetapi permintaan dari Presenter untuk data. Ini jauh lebih bersih, karena Presenter mungkin sudah tahu sebelumnya, misalnya, bahwa itu tidak memerlukan data, semuanya sama, semuanya buruk.

Selanjutnya, paragraf ketiga tentang Presenter adalah validasi JS jujur. Kita sudah bisa menulisnya dengan aman, ini adalah tempat khusus untuk itu. Panah keempat - data masuk ke model, misalnya, memasukkannya ke dalam database, mengatakan: "Semuanya beres, saya letakkan." Panah kelima, Anda lihat, bergaris-garis, saya harap jelas bahwa bergaris-garis kuning-hijau, dan manajemen dan data kembali ke Presenter. Model mengatakan "Aku meletakkannya", Presenter menyadari bahwa karena data dimasukkan ke dalam database, itu berarti bahwa perlu untuk menampilkan bahwa semuanya beres, data dimasukkan. Dan panah keenam - mereka mengirimnya ke tampilan, mungkin ke yang lain, tapi kemudian saya tidak menggambar pandangan kedua.

Apa kelebihannya di sini. Validasi JS jatuh ke tempatnya yang benar dan semuanya menjadi baik-baik saja dengan itu, AJAX juga jatuh ke tempatnya, ini mungkin panah keempat, misalnya, jika model ada di server, atau model AJAX sendiri masuk ke server. Dan akhirnya, kita dapat dengan aman menguji Presenter, menulis tes fungsional di atasnya.



Kedua, apa lagi yang kami dapatkan dari hasil positif, selain pengujian yang disederhanakan? Kami mendapat pemisahan tampilan visual dan pekerjaannya. Artinya, kita masih dapat menulis snapshot pada Tampilan, dan kita dapat menulis tes pada Presenter secara terpisah. Kami dapat memperbaiki Presenter dan tidak menyentuh View, dan sebaliknya. Spesialisasi kami telah meningkat. Ini adalah bagaimana kerangka kerja seperti Angular1, Backbone, Ember, Knockout dari versi sebelumnya disusun. Dulu ada banyak dari mereka, hanya persaingan sengit.

Apa saja fiturnya. Presenter sudah ditempatkan pada klien, modelnya bisa ada di sana, dan ada satu halaman aplikasi yang dibuat dengan diam-diam. Itu terjadi lebih baik, tetapi ada banyak aplikasi satu halaman pada cerita ini, atau setidaknya sudah dilakukan sebelumnya. Interaksi server AJAX baik. Validasi klien sudah ada. Tampaknya semuanya baik-baik saja, mengapa berpikir lebih jauh?

Namun, setidaknya MVVM ditemukan. Juga hal yang menarik.



Intinya, ini adalah implementasi dari Presenter menggunakan framework. Sering kali ternyata ketika Anda menulis Presenter pertama, Presenter kedua, Presenter kelima, semuanya sama. Dan mereka hanya merajut tampilan dan model. Seperti yang Anda lihat, itu dibangun seperti MVP.



Dan begitu banyak kerangka kerja yang baru saja menyelesaikan tugas-tugas yang mengikat ini. Apa kelebihannya? Kami tidak perlu menulis kode tambahan. Dan itu benar-benar mempercepat kecepatan pengembangan. Apa kerugiannya? Konektivitas antara Model dan ViewModel ditingkatkan.

Artinya, masalah muncul di sana justru karena keterhubungan yang kuat, sehingga terkadang MVVM tidak digunakan. Sebagai contoh, saya secara pribadi terbiasa dengan MVVM dalam kerangka kerja i-BEM, yang kadang-kadang kita gunakan, dan kadang-kadang tidak digunakan, karena ini merupakan ikatan yang tidak nyaman dan terlalu ketat. Namun, ada, Microsoft Silverlight diatur oleh teknologi ini, dan mereka berkata: bagus. Saya tidak tahu, saya belum mencobanya.

Mengapa itu terjadi bahwa selain MVP dan MVVM, sesuatu yang lain muncul, Anda semua akrab dengan kata redux, mengapa ada aliran data searah.



Kami melihat gambar yang tepat. Kami dengan MVP secara teratur memiliki masalah seperti itu. Misalkan kita memiliki sistem yang kompleks, bukan satu banding satu - banyak tampilan, banyak model. Mereka semua saling berhubungan. Pemandangan dari atas, kuning, mengubah model. Model telah mengubah model lain. Tampilan kuning bawah telah berubah. Tampilan bawah juga mengubah model. Mereka semua bersama-sama mengubah pandangan merah sentral, dan sesuatu yang tidak dapat dipahami terjadi di dalamnya.

Facebook menghadapi ini ketika mereka terus-menerus mendapat bug karena pop-up pesan yang belum dibaca. Artinya, pengguna melihat "Anda memiliki pesan yang belum dibaca", terbuka, tetapi tidak. Karena kedua pandangan bersama-sama mengoreksi keadaan yang satu ini ... Secara umum, keadaan pandangan itu dikoreksi dari dua sumber yang berbeda, dan siapa yang benar tidak jelas. Mereka memutuskan, bug muncul lagi, mereka memerintah lagi, bug muncul lagi. Pada akhirnya, mereka lelah, dan mereka memutuskan untuk menyelesaikan masalah secara radikal, menyesal atas tautologi, dan hanya membuat keadaan tampilan deterministik.

Masalah MVP justru di non-determinisme dari keadaan sistem. Kami tidak selalu dapat memprediksi dalam kondisi apa dia sekarang, dan siapa yang datang lebih dulu, siapa yang mengoreksi apa. Flux memecahkan masalah ini, seperti yang mereka katakan, secara genetik. Dia tidak bisa memilikinya. Mereka mengatakan kepada saya di sini untuk waktu yang lama bahwa ide dengan aliran data searah ada di udara, itu benar. Dan konsep ini diciptakan, tentu saja, jauh sebelum Facebook, jauh sebelum 2013, ketika mereka menerbitkannya. Tetapi mereka, seperti yang mereka katakan, telah mematenkan, pertama-tama mereka merilis sebuah spreadshit, bahwa kita datang dengan hal seperti itu, menggunakannya.



Mari kita lihat Flux lebih detail. Inilah idenya. Kami memiliki Toko, dan Toko ini adalah gudang data, ini adalah satu-satunya sumber kebenaran untuk aplikasi kami. Segala sesuatu yang lain tidak benar. Bagaimana cara kerjanya? Pada awalnya, jika kita melihat secara spesifik pada siklus kerja, biasanya dimulai dengan pengguna melakukan sesuatu, yaitu, tampilan berfungsi. Lihat membuat Action. Harap dicatat bahwa Action tidak diisi dalam gambar. Kenapa begitu Karena itu adalah struktur. Ini bukan kelas, bukan objek, itu bukan sesuatu yang pintar. Ini strukturnya. Di web, dalam JavaScript kita bisa menulisnya, hanya saja objek yang sangat abstrak itu.

Pandangan menciptakan struktur, lolos ke manajer blok. Manajer blok memicu panggilan balik. Artinya, katanya: "Panggil fungsi yang saya diberitahu untuk menelepon ketika Aksi terjadi. Dia mengatakan untuk memanggil Toko. " Yaitu, metode Store dipanggil dari dispatcher. Metode ini disebut. Metode ini disebut, diperoleh di Store. Toko melihat apa yang terjadi padanya, entah bagaimana berubah sendiri. Dia mengubah kondisinya. Dan dia adalah satu-satunya yang dapat mengubah kondisinya. Tidak ada orang lain yang melakukan ini. Artinya, dia adalah satu-satunya sumber kebenaran. Setelah itu, ia menyiarkan semua pandangan yang terkait dengannya, semua komponen yang terkait dengannya: "Saya telah berubah, dapatkan data."

Pandangan pergi untuk data, dan kemudian momen yang menarik dimulai. Dalam Flux klasik, seperti yang ada di Facebook, tampilan digambar ulang sepenuhnya.



Ini formulir kami dengan label dan tombol. Bagaimana cara kerjanya? Kami melihat titik nol. Titik nol juga ada di sini. Dia adalah panah biru di bagian paling bawah, pendaftaran panggilan balik. Inilah yang terjadi pertama kali.

Manajer toko memanggil: "Tolong daftarkan callback saya, apa yang akan saya lakukan ketika Action mendatangi Anda." Itu terjadi. Lalu kita bisa bekerja dengan aplikasi tersebut. Kami mengklik tombol, membuat struktur. Harap dicatat bahwa selain data yang dimasukkan oleh pengguna, misalnya, Vasya, Action juga memiliki metadata, ketik. Poin yang sangat penting adalah bahwa Action itu sendiri menyampaikan Action seperti apa itu, tetapi bagi pihak pengirim. Dia melempar semua siaran Action. Panah pertama, metode ini disebut.

Dispatcher memanggil metode, pada kenyataannya, sebuah pemicu Action dan melewati Action ini di sana. Pada pemicu Tindakan, panggilan balik disebut, yang kami daftarkan di titik nol. Ini adalah panah merah, ini adalah panggilan panggilan balik dari panggilan balik. Toko mengambil data ini, terlihat bahwa, ya, jenisnya adalah mengubah nama, jadi saya mengubah diri saya di bidang nama ke Vasya, dan mengirimkannya ke back-end, dan entah bagaimana memvalidasi, mungkin, secara umum, Toko tahu apa yang harus dilakukan . Selanjutnya, panah ungu akan menampilkan perubahan acara. Kami telah berubah. Semua orang tahu bahwa kami telah mengubah Store.

Selanjutnya, fitur kecil dari Flux klasik, yang mungkin asing bagi mereka yang bekerja dengan Redux, lebih tepatnya, bahkan dengan React, dan bukan dengan Redux. Tampilan digunakan untuk data. Mereka pergi ke Toko dan berkata: "Saya memiliki bidang ini, bidang ini dan bidang ini." Kami terbiasa dengan kenyataan bahwa, sebaliknya, semuanya datang ke pandangan jika Anda bekerja dengan React, Redux, atau sesuatu seperti itu. Dan poin keenam, redraw total.

Mari kita lihat diagram ini dan temukan bottleneck, karena apa? Menggambar ulang. Penataan ulang yang lengkap, itulah sebabnya Flux mulai digunakan secara aktif setelah 2013, kapan apa yang muncul? Apa yang memungkinkan ini terjadi? Rumah virtual. Sebuah rumah virtual yang memungkinkan Anda untuk menggambar kembali hanya ketika itu benar-benar diperlukan.



Mari kita minggir dan berbicara tentang React, yang seperti itu, sangat berhasil dikombinasikan dengan Flux, membuat dunia yang kita kenal sekarang ketika teknologi ini paling populer.

2013 yang sama, 2013 yang sama, Facebook yang sama. Awalnya, React diciptakan secara umum, sebagai pemberitahuan tampilan di MVC, MVP, variasi. Dan itu memang bisa digunakan di sana. Apa kekuatannya. Pertama, rumah virtual, seperti yang mereka katakan dengan benar, memungkinkan untuk tidak menggambar ulang rumah yang sebenarnya, karena ini adalah operasi yang sangat sulit, tetapi untuk menggambar ulang yang virtual. Dan hanya jika, memang, ada perubahan, kami menggambar ulang komponen, sebagai hasilnya semuanya bekerja lebih cepat dari yang seharusnya.

Dan - komponen abadi murni. Ini adalah mekanisme properti. Implementasinya juga reaktif, memungkinkan Anda membuat komponen yang tidak memiliki status sendiri. Dan jika Anda menulis dalam arsitektur ini, sangat tepat untuk membuat komponen bersih, tanpa status, tanpa status. Mereka hanya memiliki data yang berasal dari Store, dan dia menggambarnya. Mereka nyaman untuk diuji, mereka jarang patah. Apa yang statis cukup sulit untuk dipatahkan, dan pengujiannya mudah.

Aplikasi yang dikombinasikan dengan arsitektur Flux sangat kuat. Mungkin, banyak orang tahu bahwa ini adalah hal yang sangat kuat. Apa pentingnya yang harus disebutkan? Selain React Redux, ada banyak bundel lainnya. Dan Anda mungkin tahu bahwa ada Angular kedua. Ini juga merupakan kombinasi dari kerangka kerja reaktif dan arsitektur Flux. Vue, Flux Redux — Fluxxor, MobX . . React Redux. Vue, , , React Redux. .



? , React Redux . Vue, . — . — MVC-. . . - React Redux .

MVP/MVVM- . , — , , . single page application, multiple page application. - - . , -, - . , MVP, .

— single page application , , . . Flux React Redux, View, Angular, MobX, Fluxxor . .

. .

> MVC: Smalltalk-80 , General MVC , ASP.NET , MVC on Web
> MVP: MVP vs MVC , GUI Architecture , Backbone , Angular1
> MVVM: MS Silverlight , i-BEM
> Flux: Hexlet , Flux for stupid people , Flux official , ReactJS , VueJS
> : , «Javascript. » , ., « » , D.Garlain, M.Shaw, ”An introduction to Software Architecture” (1994), E.Dijkstra ”GOTO statement considered harmful” (1968)

MVC, MVP, MVVM . , . Flux . , , . , — . . JavaScript. . ES5, «JavaScript. » , ES6- — , , , .

, « ». . Java, . , , Flux, . MVP, — -. , . .

, , « ». , , , , , . «GOTO operator considered harmful». . , .

. . . , - , . , , Flux, , input Flux. — , , - . . , . , . .

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


All Articles