|
| 1 | +--- |
| 2 | +title: Архітектура |
| 3 | +description: Огляд рекомендованих архітектурних шаблонів при використанні bloc. |
| 4 | +--- |
| 5 | + |
| 6 | +import DataProviderSnippet from '~/components/architecture/DataProviderSnippet.astro'; |
| 7 | +import RepositorySnippet from '~/components/architecture/RepositorySnippet.astro'; |
| 8 | +import BusinessLogicComponentSnippet from '~/components/architecture/BusinessLogicComponentSnippet.astro'; |
| 9 | +import BlocTightCouplingSnippet from '~/components/architecture/BlocTightCouplingSnippet.astro'; |
| 10 | +import BlocLooseCouplingPresentationSnippet from '~/components/architecture/BlocLooseCouplingPresentationSnippet.astro'; |
| 11 | +import AppIdeasRepositorySnippet from '~/components/architecture/AppIdeasRepositorySnippet.astro'; |
| 12 | +import AppIdeaRankingBlocSnippet from '~/components/architecture/AppIdeaRankingBlocSnippet.astro'; |
| 13 | +import PresentationComponentSnippet from '~/components/architecture/PresentationComponentSnippet.astro'; |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +Використання бібліотеки bloc дозволяє нам розділити наш додаток на три шари: |
| 18 | + |
| 19 | +- Представлення |
| 20 | +- Бізнес-логіка |
| 21 | +- Дані |
| 22 | + - Сховище |
| 23 | + - Постачальник даних |
| 24 | + |
| 25 | +Ми почнемо з найнижчого шару (найбільш віддаленого від користувацького |
| 26 | +інтерфейсу) та рухатимемося вгору до шару представлення. |
| 27 | + |
| 28 | +## Шар даних |
| 29 | + |
| 30 | +Відповідальність шару даних полягає в отриманні/маніпулюванні даними з одного |
| 31 | +або кількох джерел. |
| 32 | + |
| 33 | +Шар даних можна розділити на дві частини: |
| 34 | + |
| 35 | +- Сховище |
| 36 | +- Постачальник даних |
| 37 | + |
| 38 | +Цей шар є найнижчим рівнем додатку та взаємодіє з базами даних, мережевими |
| 39 | +запитами та іншими асинхронними джерелами даних. |
| 40 | + |
| 41 | +### Постачальник даних |
| 42 | + |
| 43 | +Відповідальність постачальника даних полягає в наданні необроблених даних. |
| 44 | +Постачальник даних повинен бути універсальним та багатофункціональним. |
| 45 | + |
| 46 | +Постачальник даних зазвичай надає прості API для виконання |
| 47 | +[CRUD](https://uk.wikipedia.org/wiki/CRUD) операцій. Ми можемо мати методи |
| 48 | +`createData`, `readData`, `updateData` та `deleteData` як частину нашого шару |
| 49 | +даних. |
| 50 | + |
| 51 | +<DataProviderSnippet /> |
| 52 | + |
| 53 | +### Сховище |
| 54 | + |
| 55 | +Шар сховища — це обгортка навколо одного або кількох постачальників даних, з |
| 56 | +якими спілкується шар Bloc. |
| 57 | + |
| 58 | +<RepositorySnippet /> |
| 59 | + |
| 60 | +Як ви можете бачити, наш шар сховища може взаємодіяти з кількома постачальниками |
| 61 | +даних та виконувати перетворення даних перед передачею результату на шар |
| 62 | +бізнес-логіки. |
| 63 | + |
| 64 | +## Шар бізнес-логіки |
| 65 | + |
| 66 | +Відповідальність шару бізнес-логіки полягає у відповіді на введення з шару |
| 67 | +представлення новими станами. Цей шар може залежати від одного або кількох |
| 68 | +сховищ для отримання даних, необхідних для побудови стану додатку. |
| 69 | + |
| 70 | +Думайте про шар бізнес-логіки як про міст між користувацьким інтерфейсом (шар |
| 71 | +представлення) та шаром даних. Шар бізнес-логіки сповіщається про події/дії з |
| 72 | +шару представлення, а потім взаємодіє зі сховищем, щоб побудувати новий стан для |
| 73 | +використання шаром представлення. |
| 74 | + |
| 75 | +<BusinessLogicComponentSnippet /> |
| 76 | + |
| 77 | +### Взаємодія між блоками |
| 78 | + |
| 79 | +Оскільки блоки надають потоки, може виникнути спокуса створити блок, який |
| 80 | +прослуховує інший блок. Ви **не повинні** робити цього. Існують кращі |
| 81 | +альтернативи, ніж вдаватися до коду нижче: |
| 82 | + |
| 83 | +<BlocTightCouplingSnippet /> |
| 84 | + |
| 85 | +Хоча наведений вище код не містить помилок (і навіть очищується за собою), він |
| 86 | +має більш серйозну проблему: він створює залежність між двома блоками. |
| 87 | + |
| 88 | +Як правило, залежностей між двома сутностями на одному архітектурному шарі слід |
| 89 | +уникати за будь-яку ціну, оскільки це створює тісний зв'язок, який важко |
| 90 | +підтримувати. Оскільки блоки знаходяться на архітектурному шарі бізнес-логіки, |
| 91 | +жоден блок не повинен знати про будь-який інший блок. |
| 92 | + |
| 93 | + |
| 94 | + |
| 95 | +Блок повинен отримувати інформацію лише через події та з впроваджених сховищ |
| 96 | +(тобто сховищ, переданих блоку в його конструкторі). |
| 97 | + |
| 98 | +Якщо ви перебуваєте в ситуації, коли блок повинен реагувати на інший блок, у вас |
| 99 | +є два інших варіанти. Ви можете перемістити проблему на шар вище (у шар |
| 100 | +представлення) або на шар нижче (у шар домену). |
| 101 | + |
| 102 | +#### З'єднання блоків через представлення |
| 103 | + |
| 104 | +Ви можете використовувати `BlocListener` для прослуховування одного блоку та |
| 105 | +додавання події до іншого блоку щоразу, коли перший блок змінюється. |
| 106 | + |
| 107 | +<BlocLooseCouplingPresentationSnippet /> |
| 108 | + |
| 109 | +Наведений вище код запобігає необхідності `SecondBloc` знати про `FirstBloc`, |
| 110 | +заохочуючи слабкий зв'язок. Додаток |
| 111 | +[flutter_weather](/uk/tutorials/flutter-weather) |
| 112 | +[використовує цю техніку](https://github.com/felangel/bloc/blob/b4c8db938ad71a6b60d4a641ec357905095c3965/examples/flutter_weather/lib/weather/view/weather_page.dart#L38-L42) |
| 113 | +для зміни теми додатку на основі отриманої інформації про погоду. |
| 114 | + |
| 115 | +У деяких ситуаціях ви можете не захотіти зв'язувати два блоки в шарі |
| 116 | +представлення. Замість цього часто має сенс, щоб два блоки використовували одне |
| 117 | +й те саме джерело даних та оновлювалися при зміні даних. |
| 118 | + |
| 119 | +#### З'єднання блоків через домен |
| 120 | + |
| 121 | +Два блоки можуть прослуховувати потік зі сховища та оновлювати свої стани |
| 122 | +незалежно один від одного щоразу, коли змінюються дані сховища. Використання |
| 123 | +реактивних сховищ для синхронізації стану є поширеним у великомасштабних |
| 124 | +корпоративних додатках. |
| 125 | + |
| 126 | +Спочатку створіть або використовуйте сховище, яке надає `Stream` даних. |
| 127 | +Наприклад, наступне сховище надає нескінченний потік тих самих кількох ідей |
| 128 | +додатків: |
| 129 | + |
| 130 | +<AppIdeasRepositorySnippet /> |
| 131 | + |
| 132 | +Те саме сховище може бути впроваджене в кожний блок, який повинен реагувати на |
| 133 | +нові ідеї додатків. Нижче наведено `AppIdeaRankingBloc`, який видає стан для |
| 134 | +кожної вхідної ідеї додатку зі сховища вище: |
| 135 | + |
| 136 | +<AppIdeaRankingBlocSnippet /> |
| 137 | + |
| 138 | +Докладніше про використання потоків з Bloc див. у статті |
| 139 | +[Як використовувати Bloc з потоками та конкурентністю](https://verygood.ventures/blog/how-to-use-bloc-with-streams-and-concurrency). |
| 140 | + |
| 141 | +## Шар представлення |
| 142 | + |
| 143 | +Відповідальність шару представлення полягає у визначенні того, як відмалювати |
| 144 | +себе на основі одного або кількох станів блоків. Крім того, він повинен |
| 145 | +обробляти введення користувача та події життєвого циклу додатку. |
| 146 | + |
| 147 | +Більшість потоків додатків починаються з події `AppStart`, яка запускає додаток |
| 148 | +для отримання деяких даних для представлення користувачеві. |
| 149 | + |
| 150 | +У цьому сценарії шар представлення додасть подію `AppStart`. |
| 151 | + |
| 152 | +Крім того, шар представлення повинен буде визначити, що відмалювати на екрані на |
| 153 | +основі стану з шару bloc. |
| 154 | + |
| 155 | +<PresentationComponentSnippet /> |
| 156 | + |
| 157 | +До цього моменту, хоча у нас були деякі фрагменти коду, все це було досить |
| 158 | +високорівневим. У розділі посібників ми об'єднаємо все це разом, коли будемо |
| 159 | +створювати кілька різних прикладів додатків. |
0 commit comments