Что же касается имеющейся чисто технической информации, то вам нужно поработать над подачей и оформлением. Минимально – перечитать ещё раз и обратить внимание на семантические и синтаксические ошибки, применить `dart format` к коду и выбрать язык dart для подсветки синтаксиса, проследить полноту информации ваших скриншотов. Сейчас читать это близко к невозможному.
Если же мы возвращаем void, а не значение вместо value в then ставим прочерк(_).
Это не так. Я перечитал несколько раз данное предложение и это всё ещё не так. Мы ставим прочерк в том случае, когда аргумент нам не нужен. Мы не собираемся его использовать, вот и всё. Это лучше выражает наши намерения и делает код семантически ясней.
Спасибо за материал! Скажите, как связаны ваши сервисы и репозитории? Исходя из схемы оба слоя имеют доступ к моделям, что понятно, однако кажется, что отсутствует связь между сервисами и репозиториями.
Может быть неудобным каждый раз добавлять ключ (и стоит также сказать, что ключи придётся узнать для начала :) ). Хотя, если это сильно важно, можно воспользоваться "Другие результаты с сайта ...", что приведёт нас в ту же точку.
На самом деле есть несколько преимуществ, кроме самого "поиска", который бьёт минусом в SO. Предложу лично взглянуть на два скрина - поиск из гугла и поиск из SO:
Клац
Запрос - "how to use record in dart"
Замечу, что оба поиска имеют 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'шка совместимости в помощь).
Что же касается имеющейся чисто технической информации, то вам нужно поработать над подачей и оформлением. Минимально – перечитать ещё раз и обратить внимание на семантические и синтаксические ошибки, применить `dart format` к коду и выбрать язык dart для подсветки синтаксиса, проследить полноту информации ваших скриншотов. Сейчас читать это близко к невозможному.
Это не так. Я перечитал несколько раз данное предложение и это всё ещё не так. Мы ставим прочерк в том случае, когда аргумент нам не нужен. Мы не собираемся его использовать, вот и всё. Это лучше выражает наши намерения и делает код семантически ясней.
Brave Награды?)
Спасибо, это было интересное, хотя и короткое путешествие в мир оптимизаций. Как говорится, пишите ещО :)
Если сервис дёргает метод репозитория, значит он связан. На диаграмме этого не показано, вот в чём вопрос :)
Спасибо за материал! Скажите, как связаны ваши сервисы и репозитории? Исходя из схемы оба слоя имеют доступ к моделям, что понятно, однако кажется, что отсутствует связь между сервисами и репозиториями.
С радостью прочитал бы следующий материал, оправдывающий ваш применённый хаб - 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'шка совместимости в помощь).Спасибо большое, я осознал и исправил (правда, потребовалось время на осмысление)