Спасибо за материал! Скажите, как связаны ваши сервисы и репозитории? Исходя из схемы оба слоя имеют доступ к моделям, что понятно, однако кажется, что отсутствует связь между сервисами и репозиториями.
Может быть неудобным каждый раз добавлять ключ (и стоит также сказать, что ключи придётся узнать для начала :) ). Хотя, если это сильно важно, можно воспользоваться "Другие результаты с сайта ...", что приведёт нас в ту же точку.
На самом деле есть несколько преимуществ, кроме самого "поиска", который бьёт минусом в SO. Предложу лично взглянуть на два скрина - поиск из гугла и поиск из SO:
Клац
Замечу, что оба поиска имеют 2 совпадения в первых пяти результатах. Повезло, повезло)
Из SO я вижу больше метаинформации: есть ли ответы на вопросы, принят ли ответ, кем вопросы были задан и какая репутация у этого человека, сразу вижу начало тела вопроса, количество просмотров. Если долго сидишь на SO, мозг быстро считывает эти показатели в мгновение, что сильно повышает успех в поиске ответа. Плюс, неплохой фильтр результатов, если необходимо.
Что мы видим из гугла? Вопрос и дату его опубликования. Даже не понятно, есть ли ответ (кроме 1-го). И лишний клик приводит к трате времени, как правило, намного большей, чем предполагалось, если задавать не детский вопрос.
К слову, поиск на SO доступен чуть ли не всегда в верхней его части, т.е. в быстром доступе, если ты уже на SO
Благодарю за подробный материал - крайне интересно пожонглировать в воображении архитектурой! Некоторые дополнения/замечания (с учётом времени рождения статьи):
Текстовые контроллеры и прочие контроллеры рекомендуется инициализировать в initState , потому что это может быть удобным по ряду причин; одна из таких - вы можете присвоить какое-либо начальное значение на основе других данных. Затем, любые контроллеры необходимо утилизировать в методе dispose виджета (контроллеры могут быть сложней/тяжелей - привет утечка памяти).
class _HomeState extends State<Home> {
late final TextEditingController _latController;
late final TextEditingController _lngController;
HomeState _homeState;
@override
void initState() {
super.initState();
_latController = TextEditingController();
_lngController = TextEditingController();
_homeState = HomeModule.homeState();
}
@override
void dispose() {
super.dispose();
_latController.dispose();
_lngController.dispose();
}
Нераскрыта история про обработку ошибок/исключений. Сделали бы вы разделение по слоям, когда на каждом уровне был бы свой тип ошибки? Сделали бы это в алгебраическом стиле или ином?
Вероятно, реализация папки data чрезмерно сложная для простых проектов. 3 уровня вложенности можно смело заменить одним-двумя максимум + как и было указано, воспользоваться кодогенерацией и расширениями классов. И опять же, мы в мире dart - никто не отменял factory, чтобы жонглировать ModelDTO, Model, ModelUI. Тут это by design
Реализация вместо наследования:
import 'package:habr_flutter_clean_arch/data/api/api_util.dart';
import 'package:habr_flutter_clean_arch/domain/model/day.dart';
import 'package:habr_flutter_clean_arch/domain/repository/day_repository.dart';
class DayDataRepository extends DayRepository {...}
// может всё-таки реализуем контракт?
class DayDataRepository implements DayRepository {...}
Конечно, сейчас для внедрения зависимостей стоит воспользоваться provider,getIt,injectable или что-то в этом духе. Если научитесь делать чистый Inherited тоже будет удобно. Опять же, of(context) - это сок дерева flutter
Часто приходится использовать что-то в духе mvvс и иметь view-model для управления некоторым (сложным и не очень) состоянием view. В данном случае так же встаёт вопрос о роутинге, который может быть сильно подвязан к ? чему угодно в некоторых проектах, что я видывал. Где он будет размещён, какую роль играет?
Вопросы тестирования данных сервисов/репозиториев/бизнес-логики. В долгоживущих проектах это критически важно. Как это можно реализовать и в том числе с учетом такого кода?:
final Dio _dio = Dio(
BaseOptions(baseUrl: _BASE_URL),
);
Да, входит. Но мы не можем из пакета flutter_bloc вызывать сущности пакета provider. Разве что, кроме этих
Если говорить коротко - provider нужен flutter_bloc'у для внедрения зависимостей в дерево виджетов. Удобного и признанного. И можно делать аналогии а-ля BlocProvider это обёртка над Provider, что несомненно, так и есть, но внутри каждый из них выглядит по-своему. И нет такого, что BlocProvider extends Provider
Здравствуйте. Спасибо за материал! Было бы неплохо добавить красок коду, указав язык для сниппетов - dart, а также убрать дублирование кода в разделе "Перейдем к логике авторизации"
Возможно, стоит привязать `disconnect()` к `dispose()` методу виджета в дальнейшем, хоть это и крайне простой пример приложения)
Более того, даже модификаторы – вещь абсолютно необязательная (по крайней мере, пока). С другой стороны, их внедрение позволяет лучше контролировать api-пакетов. Раньше нужно было бы указать в документации о том, как можно использовать "этот вот класс". А теперь всё крайне очевидно (а если нет, то справочник Брайля png'шка совместимости в помощь).
В OF меня очень сильно расстраивала невозможность перезарядки при беге. Наш герой просто останавливался и, кажется, успевала пройти вся вечность, пока магазин будет заменён. Естественно, в этот момент простоя можно было смело словить пулю.
А так, шикарная игра. И редактор есть, и две интереснейшие компании сюжетные, и отдельные миссии. И самое главное, свобода действий, как верно подметили в статье.
А вот "вторая часть" - Red River - меня очень разочаровала после первых часов игры.
Спасибо за материал! Скажите, как связаны ваши сервисы и репозитории? Исходя из схемы оба слоя имеют доступ к моделям, что понятно, однако кажется, что отсутствует связь между сервисами и репозиториями.
С радостью прочитал бы следующий материал, оправдывающий ваш применённый хаб - flutter :)
Какой менеджер состояния использовали, как устроена архитектура приложения, маршрутизация, локализация...
Может быть неудобным каждый раз добавлять ключ (и стоит также сказать, что ключи придётся узнать для начала :) ). Хотя, если это сильно важно, можно воспользоваться "Другие результаты с сайта ...", что приведёт нас в ту же точку.
На самом деле есть несколько преимуществ, кроме самого "поиска", который бьёт минусом в SO. Предложу лично взглянуть на два скрина - поиск из гугла и поиск из SO:
Клац
Замечу, что оба поиска имеют 2 совпадения в первых пяти результатах. Повезло, повезло)
Из SO я вижу больше метаинформации: есть ли ответы на вопросы, принят ли ответ, кем вопросы были задан и какая репутация у этого человека, сразу вижу начало тела вопроса, количество просмотров. Если долго сидишь на SO, мозг быстро считывает эти показатели в мгновение, что сильно повышает успех в поиске ответа. Плюс, неплохой фильтр результатов, если необходимо.
Что мы видим из гугла? Вопрос и дату его опубликования. Даже не понятно, есть ли ответ (кроме 1-го). И лишний клик приводит к трате времени, как правило, намного большей, чем предполагалось, если задавать не детский вопрос.
К слову, поиск на SO доступен чуть ли не всегда в верхней его части, т.е. в быстром доступе, если ты уже на SO
А кто-нибудь подскажет, как правильно "гуглить" вопрос на самом сайте stackoverflow?
Пишу там в поиске - ноль в выдаче. Пишу запрос в гугл - ссылки с правильными вопросами в stackoverflow...
Благодарю за подробный материал - крайне интересно пожонглировать в воображении архитектурой! Некоторые дополнения/замечания (с учётом времени рождения статьи):
Текстовые контроллеры и прочие контроллеры рекомендуется инициализировать в
initState
, потому что это может быть удобным по ряду причин; одна из таких - вы можете присвоить какое-либо начальное значение на основе других данных. Затем, любые контроллеры необходимо утилизировать в методеdispose
виджета (контроллеры могут быть сложней/тяжелей - привет утечка памяти).Нераскрыта история про обработку ошибок/исключений. Сделали бы вы разделение по слоям, когда на каждом уровне был бы свой тип ошибки? Сделали бы это в алгебраическом стиле или ином?
Вероятно, реализация папки
data
чрезмерно сложная для простых проектов. 3 уровня вложенности можно смело заменить одним-двумя максимум + как и было указано, воспользоваться кодогенерацией и расширениями классов. И опять же, мы в мире dart - никто не отменял factory, чтобы жонглировать ModelDTO, Model, ModelUI. Тут это by designРеализация вместо наследования:
Конечно, сейчас для внедрения зависимостей стоит воспользоваться
provider,
getIt,
injectable
или что-то в этом духе. Если научитесь делать чистыйInherited
тоже будет удобно. Опять же,of(context)
- это сок дерева flutterЧасто приходится использовать что-то в духе mvvс и иметь view-model для управления некоторым (сложным и не очень) состоянием view. В данном случае так же встаёт вопрос о роутинге, который может быть сильно подвязан к ? чему угодно в некоторых проектах, что я видывал. Где он будет размещён, какую роль играет?
Вопросы тестирования данных сервисов/репозиториев/бизнес-логики. В долгоживущих проектах это критически важно. Как это можно реализовать и в том числе с учетом такого кода?:
Да, входит. Но мы не можем из пакета flutter_bloc вызывать сущности пакета provider. Разве что, кроме этих
Если говорить коротко - provider нужен flutter_bloc'у для внедрения зависимостей в дерево виджетов. Удобного и признанного. И можно делать аналогии а-ля
BlocProvider
это обёртка надProvider
, что несомненно, так и есть, но внутри каждый из них выглядит по-своему. И нет такого, чтоBlocProvider extends Provider
Спасибо! Очень интересный материал ?
Здравствуйте. Спасибо за материал! Было бы неплохо добавить красок коду, указав язык для сниппетов - dart, а также убрать дублирование кода в разделе "Перейдем к логике авторизации"
Возможно, стоит привязать `disconnect()` к `dispose()` методу виджета в дальнейшем, хоть это и крайне простой пример приложения)
Обычно к такому определению я также добавляю
чтобы явно показать принадлежность и намерения
"copyWith" нет, "==/hashcode" нет, -- кажись никак :)
Разве что, теперь мы можем делать это
вместо when/map
Интересная история. С радостью прочту статью о применяемых либах в flutter приложении -- менеджер состояния, архитектура проекта, хранилище :)
Спасибо, интересное у вас приложение. Немного непривычный интерфейс, однако, чувствуется, как вы вложили душу :))
Более того, даже модификаторы – вещь абсолютно необязательная (по крайней мере, пока). С другой стороны, их внедрение позволяет лучше контролировать api-пакетов. Раньше нужно было бы указать в документации о том, как можно использовать "этот вот класс". А теперь всё крайне очевидно (а если нет, то
справочник Брайляpng'шка совместимости в помощь).Спасибо большое, я осознал и исправил (правда, потребовалось время на осмысление)
Честно говоря, это не выглядит проще, чем сделать тоже самое на flutter...
Собственно, с ней что-то не так?
В OF меня очень сильно расстраивала невозможность перезарядки при беге. Наш герой просто останавливался и, кажется, успевала пройти вся вечность, пока магазин будет заменён. Естественно, в этот момент простоя можно было смело словить пулю.
А так, шикарная игра. И редактор есть, и две интереснейшие компании сюжетные, и отдельные миссии. И самое главное, свобода действий, как верно подметили в статье.
А вот "вторая часть" - Red River - меня очень разочаровала после первых часов игры.
Nylo - впервые слышу о таком. Что за зверь?
С радостью прочёл бы статью о применяемой связке. Она в целом очевидна, за исключением Riverpod + DI. Спасибо за материал!