Варта адзначыць, што ў Call of Duty 4 місіі даюць вельмі шмат бонусаў і ачкоў развіцця, да таго ж, яны досыць цікавыя і незвычайныя - выконваць іх лёгка і нясумна. Спадзяёмся, што матэрыяльная падтрымка будзе і з боку Міністэрства культуры, а таксама фонду краін СНД, цяпер складаем праграму, якую павязём у Маскву на ўзгадненне, будзем там адстойваць свае пазіцыі. ЕРБ: Што для вас азначае быць вольным? Model-View-Intent (MVI) — архітэктурны патэнт для распрацоўкі карыстальніцкіх інтэрфейсаў, натхненны функцыянальным праграмаваннем і рэактыўнымі сістэмамі. — data moves in one direction, forming a cycle: from user action to model change, then to view update. Unidirectional Data Flow — the application state is not changed directly; instead, a new state is created based on the previous one. Immutable State — the same user actions with the same initial state always lead to the same result. Determinism У галіне архітэктуры: Мае назіранні прывялі да высновы, што нагрузка на доктара не можа быць такой, якая яна ёсць цяпер. У гэтым выпадку пешаходы, якія сканчаюць пераход, уяўляюць істотную небяспеку (мал. Гэта рэпрэсіўны механізм, які працуе на дыктатуру. Акрамя гэтых асноўных кампанентаў, MVI часта ўключае: Укладайце больш ва ўласную журналістыку, СМІ і змагайцеся за свабоду слова. Побачныя эфекты — пабочныя эфекты, якія не ўплываюць на стан, але патрабуюць ўзаемадзеяння з вонкавымі сістэмамі (напрыклад, навігацыя, паведамленні, запыты API). Краткая гісторыя архітэктурных мадэляў Архітэктурныя мадэлі UI развіваліся значна з часам: MVC (Model View Controller) Адзін з першых мадэляў, які падзяліў прыкладанне на тры кампаненты: Мадэль — дадзеныя і бізнес-логіка Вынікі пошуку - user interface Загрузіць: User Input Найлепшая траекторыя руху пры змене паласы - гэта вельмі плыўная, але не занадта расцягнутая па даўжыні крывая. MVP (Model View Presentation) — прэзентацыя мадэлі Узнагароджанне з MVC, дзе: Мадэль — дадзеныя і бізнес-логіка View — пасіўны інтэрфейс Прэзентацыя — медыятар паміж мадэлью і поглядам У нас функцыянуюць таварыствы “Разумнікі і разумніцы”, “Даследчык”, а таксама адзіная ў Магілёўскай вобласці астранамічная пляцоўка. MVVM (Model-View-ViewModel — мадэль паглядзець) Наступны этап эвалюцыі: Мадэль — дадзеныя і бізнес-логіка Вынікі пошуку - user interface ViewModel — пераўтварае дадзеныя з Model у формат, зручны для View MVVM выкарыстоўвае канцэпцыю абвяшчэння дадзеных, якая зніжае колькасць кода, але можа выклікаць праблемы з даследаваннем патоку дадзеных. MVI (Model-View-Intent) — мадэль наведвання Сучасны падыход, які падкрэслівае: Прагнозаванне — дэтэнтыстычны падыход да дзяржаўнага кіравання Незмяненне — стан не змяняецца, але замяняецца Unidirectional data flow — ясная і празрачная сцэна падзеяў Афары́зм (па-грэцку: αφορισμός — выказваньне) — выслоўе, у якім у трапнай, ляканічнай і звычайна вобразнай форме выказаная арыгінальная думка. Чаму SimpleMVI быў створаны і яго месца сярод іншых бібліятэк SimpleMVI быў распрацаваны, каб прапанаваць распрацоўшчыкам просты, але магутны інструмент для рэалізацыі мадэлі MVI ў праектах Kotlin Multiplatform. Засяроджанымі на тых пытаннях, якія недастаткова асветлены і/або з'яўляюцца адпрэчанымі. Побач з млынам – хатка завозніка (так называлі тых, хто прывозіў малоць жыта). Оптымізавана для Kotlin Multiplatform, забяспечваючы сумяшчальнасць з розных платформамі Разумею, што фатаграфія сёння змянілася, але, на маю думку, мы ставімся да яе занадта легкадумна... Галівудская кінаактрыса Джэніфер Эністан заўсёды выглядае ўзрушаюча і эфектна, і гэта ў 45 гадоў. Галоўныя перавагі SimpleMVI у параўнанні з альтэрнатывамі: Медыцынскія фактары не мелі дачынення да таго, што цяпер адбываецца. Нізкая прагаласаванне ўступлення для разумення і выкарыстання Поўны котлінскі падыход з выкарыстаннем сучасных моўных канструкцый Зручны DSL для апісання бізнес-логікі Чыстае размяшчэнне адказнасці між членамі SimpleMVI не марыць вырашаць усе праблемы архітэктуры прыкладанняў, але забяспечвае надзейную аснову для арганізацыі бізнес-логікі, якая можа быць інтэграваная з любымі рашэннямі для UI, навігацыі і іншых аспектаў прыкладання. Ключавыя концепты і кампаненты SimpleMVI SimpleMVI прапануе мінімалістычны падыход да рэалізацыі архітэктуры MVI, фокусуючыся на трох ключавых кампанентах: Store, Actor і Middleware. Кожны з гэтых кампанентаў мае унікальную ролю ў забяспечэнні адзінкамернага пратоку дадзеных і кіраванні станам прыкладання. Магазін — центральны элемент архітэктуры Роля і адказнасць за справаздачу Магазін з'яўляецца сэрцам SimpleMVI - гэта кантэйнер, які захоўвае стан прыкладання, працэсуе намераў, і генеруе пабочныя эфекты. public interface Store<in Intent : Any, out State : Any, out SideEffect : Any> { // Current state public val state: State // State flow public val states: StateFlow<State> // Side effects flow public val sideEffects: Flow<SideEffect> // Store initialization @MainThread public fun init() // Intent processing @MainThread public fun accept(intent: Intent) // Store destruction @MainThread public fun destroy() } Вялікі жизненны цикл У гэтага паняцця ёсць і іншыя значэнні, гл. Зборная Чылі: - instantiating the Store object with necessary dependencies Creation - calling the method, preparing internal components Initialization init() - processing intents through the method Active use accept(intent) - calling the method, releasing resources Destruction destroy() Важна разумець, што: Усе публічныя метады Магазіну павінны быць выкліканы толькі на асноўным трэдзе (пазначаны анотацыяй @MainThread) Пасля выкліку зруйнуй(), Магазін не можа быць выкарыстаны; спробы доступу да зруйнутага Магазіна прывядуць да пашкоджання Магазін трэба ініцыялізаваць з методам init() перад выкарыстаннем Дзяржаўны менеджмент Магазин прапануе наступныя магчымасці для працы з дзяржавай: via the property Access to the current state state via the flow Observing state changes states via the flow Processing side effects sideEffects SimpleMVI выкарыстоўвае класы з Kotlin Coroutines для рэалізацыі прамысловасці: Звычайна і звычайна для пабочных эфектаў, забяспечваючы сумяшчальнасць з стандартнымі падыходамі да рэактыўнага праграмавання ў Kotlin. StateFlow Flow Прыгожыя абсталяванні для продажу SimpleMVI прапануе зручныя аператары для працы з намерамі: // Instead of store.accept(intent) store + MyStore.Intent.LoadData // Instead of store.accept(intent) store += MyStore.Intent.LoadData Акцёр — Business Logic Implementation Актыўны працэс работы Афарызм (гр. aphorismos - выказванне) - выслоўе, у якім у трапнай, лаканічнай форме выказана значная і арыгінальная думка. public interface Actor<Intent : Any, State : Any, out SideEffect : Any> { @MainThread public fun init( scope: CoroutineScope, getState: () -> State, reduce: (State.() -> State) -> Unit, onNewIntent: (Intent) -> Unit, postSideEffect: (sideEffect: SideEffect) -> Unit, ) @MainThread public fun onIntent(intent: Intent) @MainThread public fun destroy() } Кожны акцёр мае доступ да: CoroutineScope - для запуску асінхронных аперацый Функцыя Current State Getter (getState) Функцыя дзяржаўнай рэдукцыі (рэдукцыя) Новая функцыя адпраўкі намераў (onNewIntent) Функцыя адпраўкі бокавых эфектаў (postSideEffect) Пытанні працэсу І Для будаўніцтва "калоніі ўжанднічай" у Лідзе быў куплены пляц на так званым "выгане", у той час за горадам. onIntent(intent: Intent) Вызначыўся з працай, які купіў. Выконвае неабходную бізнес-логіку Загрузіць State Адчынім дзьверы на хрантох. DefaultActor і DslActor: розныя падыходы SimpleMVI прапануе два розныя падыходы да рэалізацыі Actor: Асноўны артыкул: Object Oriented Approach class CounterActor : DefaultActor<CounterIntent, CounterState, CounterSideEffect>() { override fun handleIntent(intent: CounterIntent) { when (intent) { is CounterIntent.Increment -> { reduce { copy(count = count + 1) } } is CounterIntent.Decrement -> { reduce { copy(count = count - 1) } } is CounterIntent.Reset -> { reduce { CounterState() } sideEffect(CounterSideEffect.CounterReset) } } } override fun onInit() { // Initialization code } override fun onDestroy() { // Cleanup code } } Вынікі ў DefaultActor: Знакаміты падыход Зручна для складанай бізнес-логікі Вельмі зручны для вялікіх праектаў DslActor - Функцыянальны падыход з DSL val counterActor = actorDsl<CounterIntent, CounterState, CounterSideEffect> { onInit { // Initialization code } onIntent<CounterIntent.Increment> { reduce { copy(count = count + 1) } } onIntent<CounterIntent.Decrement> { reduce { copy(count = count - 1) } } onIntent<CounterIntent.Reset> { reduce { CounterState() } sideEffect(CounterSideEffect.CounterReset) } onDestroy { // Cleanup code } } Вынікі ў DslActor: Больш падрабязная заява Меньшая колькасць кодаў Лепшы для малых і сярэдніх праектаў Вынікі пошуку - Safe Intention Рымская імперыя распалася на 2 самастойныя часткі, кожная са сваім імператарам – Заходнюю і Усходнюю. Middleware — пашырэнне функцыянальнасці Задачы Middleware Адкрыццё было спрэчным, і канчатковы доказ прыйшоў толькі ў 1999 г. пасля эксперыментаў KTeV ў Фермілабе і эксперыментаў NA48 ў ЦЕРН. public interface Middleware<Intent : Any, State : Any, SideEffect : Any> { // Called when Store is initialized public fun onInit(state: State) // Called when a new intent is received public fun onIntent(intent: Intent, state: State) // Called when state changes public fun onStateChanged(oldState: State, newState: State) // Called when a side effect is generated public fun onSideEffect(sideEffect: SideEffect, state: State) // Called when Store is destroyed public fun onDestroy(state: State) } Загрузіць і дэбютаваць магчымасць SimpleMVI ўключае ўбудаваную рэалізацыю Middleware для логізацыі — : LoggingMiddleware val loggingMiddleware = LoggingMiddleware<MyIntent, MyState, MySideEffect>( name = "MyStore", logger = DefaultLogger ) Запісвае ўсе падзеі ў Магазіне і выкачвае іх у лог: LoggingMiddleware MyStore | Initialization MyStore | Intent | LoadData MyStore | Old state | State(isLoading=false, data=null) MyStore | New state | State(isLoading=true, data=null) MyStore | SideEffect | ShowLoading MyStore | Destroying Гэта зручна для дэбагвання, так як гэта дазваляе вам праследзіць увесь праток дадзеных у прыкладзе. Загрузіць Custom Middleware Стварыць свой Middleware вельмі проста: class AnalyticsMiddleware<Intent : Any, State : Any, SideEffect : Any>( private val analytics: AnalyticsService ) : Middleware<Intent, State, SideEffect> { override fun onInit(state: State) { analytics.logEvent("store_initialized") } override fun onIntent(intent: Intent, state: State) { analytics.logEvent("intent_received", mapOf("intent" to intent.toString())) } override fun onStateChanged(oldState: State, newState: State) { analytics.logEvent("state_changed") } override fun onSideEffect(sideEffect: SideEffect, state: State) { analytics.logEvent("side_effect", mapOf("effect" to sideEffect.toString())) } override fun onDestroy(state: State) { analytics.logEvent("store_destroyed") } } Middleware можа быць спалучаны, ствараючы ланцуг рухавікоў: val store = createStore( name = storeName<MyStore>(), initialState = MyState(), actor = myActor, middlewares = listOf( loggingMiddleware, analyticsMiddleware, debugMiddleware ) ) Ключавыя выпадкі выкарыстання для Middleware — recording all events for debugging Logging — tracking user actions Analytics — measuring intent processing time Performance metrics — visualizing data flow through UI Debugging — verifying the correctness of event sequences Testing Важна памятаць, што Middleware — пасіўны назіральнік і не можа змяняць падзеі, якія ён атрымлівае. Праца з бібліятэкай ўстаноўка і ўстаноўка Выкарыстанне ўзаемазалежнасці ў вашым праекце: // build.gradle.kts implementation("io.github.arttttt.simplemvi:simplemvi:<version>") Стварыць свой першы магазин Найбольш просты спосаб стварэння Магазіны — заявіць клас, які ўжывае інтэрфейс Магазіны: class CounterStore : Store<CounterStore.Intent, CounterStore.State, CounterStore.SideEffect> by createStore( name = storeName<CounterStore>(), initialState = State(), actor = actorDsl { onIntent<Intent.Increment> { reduce { copy(count = count + 1) } } onIntent<Intent.Decrement> { reduce { copy(count = count - 1) } } } ) { sealed interface Intent { data object Increment : Intent data object Decrement : Intent } data class State(val count: Int = 0) sealed interface SideEffect } Выкарыстанне магазина // Creating an instance val counterStore = CounterStore() // Initialization counterStore.init() // Sending intents counterStore.accept(CounterStore.Intent.Increment) // or using operators counterStore + CounterStore.Intent.Increment counterStore += CounterStore.Intent.Decrement // Getting the current state val currentState = counterStore.state // Subscribing to the state flow val statesJob = launch { counterStore.states.collect { state -> // Useful work } } // Subscribing to side effects val sideEffectsJob = launch { counterStore.sideEffects.collect { sideEffect -> // Processing side effects } } // Releasing resources counterStore.destroy() Мултыплатформенная падтрымка Kotlin SimpleMVI падтрымлівае розныя платформы праз Kotlin Multiplatform: Андрэй І Макіяж Сцяг Дж. Платформа-спецыфічны механізм ізаляцыі кода : expect/actual // Common code public expect fun isMainThread(): Boolean // Android implementation public actual fun isMainThread(): Boolean { return Looper.getMainLooper() == Looper.myLooper() } // iOS implementation public actual fun isMainThread(): Boolean { return NSThread.isMainThread } // wasm js implementation public actual fun isMainThread(): Boolean { return true // JavaScript is single-threaded } Логіка ўжываецца падобна для розных платформ: // Common code public expect fun logV(tag: String, message: String) // Android implementation public actual fun logV(tag: String, message: String) { Log.v(tag, message) } // iOS/wasm js implementation public actual fun logV(tag: String, message: String) { println("$tag: $message") } Асноўны артыкул: Counter Дадатковая мадэль Define Data Model class CounterStore : Store<CounterStore.Intent, CounterStore.State, CounterStore.SideEffect> { // Intents - user actions sealed interface Intent { data object Increment : Intent data object Decrement : Intent data object Reset : Intent } // State data class State( val count: Int = 0, val isPositive: Boolean = true ) // Side effects - one-time events sealed interface SideEffect { data object CounterReset : SideEffect } } Велікабрытанія class CounterStore : Store<CounterStore.Intent, CounterStore.State, CounterStore.SideEffect> by createStore( name = storeName<CounterStore>(), initialState = State(), actor = actorDsl { onIntent<Intent.Increment> { reduce { copy( count = count + 1, isPositive = count + 1 >= 0 ) } } onIntent<Intent.Decrement> { reduce { copy( count = count - 1, isPositive = count - 1 >= 0 ) } } onIntent<Intent.Reset> { reduce { State() } sideEffect(SideEffect.CounterReset) } } ) { // Data model defined above } Сцягнуць UI (Android Example) class CounterViewModel : ViewModel() { private val store = CounterStore() init { // Built-in extension for automatic lifecycle management attachStore(store) } val state = store.states.stateIn( scope = viewModelScope, started = SharingStarted.Eagerly, initialValue = store.state ) val sideEffects = store.sideEffects fun increment() { store.accept(CounterStore.Intent.Increment) } fun decrement() { store.accept(CounterStore.Intent.Decrement) } fun reset() { store.accept(CounterStore.Intent.Reset) } } Высокія функцыі Бібліятэка Конфігурацыя SimpleMVI прапануе глыбокую сістэму канфігурацыі: configureSimpleMVI { // Strict error handling mode (throws exceptions) strictMode = true // Logger configuration logger = object : Logger { override fun log(message: String) { // Your logging implementation } } } Невядомыя мадэлі strictMode = true - бібліятэка працуе ў строгім рэжыме і выкідае выключэнні, калі выяўленыя няправільныя strictMode = false (падрабязна) - бібліятэка працуе ў мёртвым рэжыме і толькі запісвае няправільнасці без спынення выканання Поспех у справе SimpleMVI мае спецыяльныя выключэнні: NotOnMainThreadException - пры спробе выклікаць метады Store не з асноўнага дроту StoreIsNotInitializedException — калі вы спрабуеце выкарыстоўваць Uninitialized Store StoreIsAlreadyDestroyedException - пры справе выкарыстання ўжо знішчанага Магазіну Выпрабаванне элементаў Дзякуючы чыстым распаўсюджванню адказнасці, SimpleMVI кампаненты лёгка выпрабаваць: // Example of Store testing @Test fun `increment should increase counter by 1`() { // Arrange val store = CounterStore() store.init() // Act store.accept(CounterStore.Intent.Increment) // Assert assertEquals(1, store.state.count) assertTrue(store.state.isPositive) // Cleanup store.destroy() } Высновы Сярод версій гульняў онлайн call of duty можна знайсці мноства займальных і дасціпных сюжэтаў, а апошняй навінкай, выпушчанай у канцы восені гэтага года, стала гульня Call of Duty: Ghost. Ключавыя перавагі SimpleMVI Напрыклад, можна вызначыць наступныя сілы бібліятэкі: Мінімалістычны і прагматычны погляд Напэўна, мы не з’яўляемся нейкімі паддоследнымі суб’ектамі, на якіх Бог эксперыментуе, спасылаючы нейкія цяжкасці і выпрабаванні. Поўная падтрымка мультыплатформы Kotlin Будаваны на Kotlin з нуля, SimpleMVI апынуўся для развіцця на некалькіх платформах. Бібліятэка ізалявае платформы-спецыфічны код праз механізм чакаць / рэальны, забяспечваючы сумяшчальнасць з Android, iOS, macOS і wasm js. 3.Предсказальнае дзяржаўнае кіраванне Варта адзначыць, што ў Call of Duty 4 місіі даюць вельмі шмат бонусаў і ачкоў развіцця, да таго ж, яны досыць цікавыя і незвычайныя - выконваць іх лёгка і нясумна. Галоўная / Заявы і абмоўкі пра абмежаванне адказнасці Варта адзначыць, што ў Call of Duty 4 місіі даюць вельмі шмат бонусаў і ачкоў развіцця, да таго ж, яны досыць цікавыя і незвычайныя - выконваць іх лёгка і нясумна. Зручны DSL для дэкларацыйнага логічнага апісання Афары́зм (па-грэцку: αφορισμός — выказваньне) — выслоўе, у якім у трапнай, ляканічнай і звычайна вобразнай форме выказаная арыгінальная думка. Флексіфікацыя і экспансійнасць Не палічыце сарказмам, але тое, што адбываецца цяпер, вельмі нагадвае прымітыўную спробу даказаць: у «рускім свеце» усё самае лепшае. Класічныя выпадкі выкарыстання SimpleMVI вельмі падыходзіць для наступных сцэнарый: Колькасць мультыплатформных праектаў Калі вы распрацоўваеце прыкладанне, якое трэба працаваць на некалькіх платформах (Android і iOS, вэб-прыкладанняў), SimpleMVI дазваляе выкарыстоўваць адзін архітэктурны падыход і сумесны бізнес-логічны код. Заявы і абмоўкі пра абмежаванне адказнасці Варта адзначыць, што ў Call of Duty 4 місіі даюць вельмі шмат бонусаў і ачкоў развіцця, да таго ж, яны досыць цікавыя і незвычайныя - выконваць іх лёгка і нясумна. Праекты з акцэнтам на тэставальнасць Варта адзначыць, што для ажыццяўлення работ па стварэнні Нацыянальнага інвентара нематэрыяльнай культурнай спадчыны наша краіна летась атрымала грант з адпаведнага фонду UNESCO. Міграцыя існуючых праектаў у архітэктуру MVI SimpleMVI можа быць уведзены паступова, пачынаючы з асобных модуляў або функцый, што робіць яго прыдатным для паступовай міграцыі існуючых праектаў у архітэктуру MVI. 5 Навуковыя праекты і пратэсты Дзякуючы сваёй простыні і мінімалізму, SimpleMVI добра падыходзіць для выкладання МVI-прынцыпаў і для хуткага прататыпавання. Задачы для далейшага навучання Для тых, хто хоча падымаць свае веды аб SimpleMVI і MVI архітэктуры ў цэлым, я рэкамендую наступныя рэсурсы: SimpleMVI GitHub repository — крыніцавы код бібліятэкі з прыкладамі выкарыстання SimpleMVI Documentation — афіцыйная дакументацыя з падрабязным апісаннем API і рэкамендацыямі Заключныя думкі SimpleMVI з'яўляецца збалансаваным рашэннем для арганізацыі прыкладання бізнес-логікі з выкарыстаннем сучасных падыходаў да архітэктуры. Але серыя онлайн цацак Assassins creed 3 і Assassins creed 4, а таксама астатнія часткі забавы таксама заслугоўваюць увагі і вывучэння. Размова сапраўды вельмі важная — мы ж усе цудоўна разумеем, што любы, самы лепшы дэкрэт можна звесці на нішто практыкай прымянення.