Как стать автором
Поиск
Написать публикацию
Обновить
18
0
Журат Максим @ChessMax

Пользователь

Отправить сообщение

Не сдюжили...

Мой первый хард был на 40 гигов. Скоро можно будет купить на 40тб).

Может, попробуете Obsidian+git как мобильный клиент?

Да возможно стоит попробовать.

Можно еще, наверное, Github mobile как клиент использовать

Github mobile использую, но он особо никак не улучшает пользовательский опыт взаимодействия с репозиторием.

Встал вопрос: в чем вести заметки? Пробовал писать текст в Intellij IDEA — редакторе кода, к горячим клавишам которого давно привык. Но отказался: IDEA — слишком громоздкая программа, предназначенная для других целей.

А я на данный момент как раз остановился на таком варианте. Просто проект, который синхронизируется через github. Записки - это просто md файлы. На компьютере работать крайне удобно. Привычные сочетания клавиш, быстрый переход к нужным файлам. В общем чувствуешь себя как дома. Вот с мобильного устройства конечно боль. Пока просто захожу на гитхаб через браузер. Пока не знаю, что с этим делать...

Ясно. Ну получается я не правильно проголосовал. Для меня играют хорошо это от кмс и выше. Остальное это любители. Мне казалось, что это плюс-минус устоявшееся определение. Хотя, вполне возможно я и не прав. В любом случае спасибо за статью!

Что значит играю хорошо и играю любительски? Каковы критерии?

В пункте о дизайн системе было бы неплохо прямо код показать как эти три вида кнопок в двух размерах будут выглядеть. Знак доллара очень неприятно смотрится (привет PHP). Фактически это шум. В дарт такое не принято. Есть ли в этом какой-то скрытый смысл?
Задумка интересная, но конкретную реализацию, я бы в свой проект не потащил.

Пункт со слабой ссылкой интересный. Получается, что API подталкивает к написанию некорректного кода?

Уже давно есть Consulo (https://github.com/consulo/consulo) так же на базе Intellij Idea. Интересно, что теперь она поддерживает (в той или иной степени) и другие языки программирования.

VSCode можно онлайн запустить с уже настроенными плагинами. Реализовывать полноценный редактор без особых на то причин, не самая полезная трата времени.

Большой процент пользователей все ещё сидит на 10-ке. Скорее всего поддержку продлят, как это уже было раньше.

Ссылка на проект, который можно запустить, конечно, не помешала бы. Количество метаданных в примере с конструктором больше чем кода самого конструктора))

Оставшиеся 2 дня, так уж и быть, пока можно работать из дома...

Динамическая типизация, когда она применяется с умом — всегда приятно и хорошо.

В приведенном примере нет никакой динамической типизации. Рекорды в дарт строго типизированы. Если не указать тип, то компилятор выводит его автоматически. Это называется type inference.

Rx.combileLatest(...)

Видимо имелось ввиду Rx.combineLatest(...)

Однако и на этом синтаксический сахар не заканчивается! Нужно познакомиться еще с двумя понятиями: Guard clause и Exhaustiveness checking.

Exhaustiveness checking - это не синтаксический сахар. Синтаксический сахар - это когда, что-то можно сделать более удобно, чем раньше, при этом старый способ все так же работает. Exhaustiveness checking можно сделать только с помощью switch, никаких других вариантов нет.

Однако же, это работает и в обратном направлении: если убрать dynamic, то анализатор, совершенно справедливо, скажет Dead code. И это действительно так, ввиду динамической типизации и понимания контекста.

Если мы убрали dynamic, то у нас нет никакой динамической типизации, как уже выше рассмотрели.

— Алгебраические типы данных. Ну, то есть красивое название для sealed-классов.

Алгебраические типы данных это не только sealed классы.

Да, на первый взгляд конструкции почти идентичные. Разница в том, что Record - это тип (который мы присвоили переменной myCoolRecord), а Pattern - это выражение.

Переменной нельзя присвоить тип, только значение. Pattern - это не выражение, так как его нельзя сохранить в переменной.

он будет создаваться всего один раз. А вот сам BLoC мы будет создавать для каждого теста единожды.

```

LoginRepository repository; LoginBloc bloc; setUp(() { repository = MockLoginRepository(); bloc = LoginBloc(repository); });

```

Текст не соответствует коду? В коде и репозиторий и блок создаются для каждого теста. При этом этот код еще и не соответствует коду в гитхабе.

final String? email;

final String? password;

Эти поля повторяются в трех классах? Может быть стоило вынести в какой-то базовый класс? Или миксин? В таком случае код геттера emailStr можно было бы значительно сократить. Еще момент в том, что во всех состояниях эти поля зануляемые, что странно. Блок как раз и славится тем, что позволяет безболезненно моделировать точные состояния.

extension LoginStateX on LoginState { String? get emailStr { if (this is LoginInitialState || this is LoginSuccessState) { return null; } else if (this is LoginDataState) { return (this as LoginDataState).email; } else if (this is LoginLoadingState) { return (this as LoginLoadingState).email; } else if (this is LoginErrorState) { return (this as LoginErrorState).email; } return null; } }

Конечно вкусовщина, но возможно стоило не создавать расширение, а перенести этот геттер прямо в класс `LoginState`? Кстати, если сохранить this в локальную переменную, то не придется писать `as LoginDataState`.

act: (_bloc) => _bloc.add(EditedEmail('example@sample.com')),

Обычно для параметров и локальных переменных не используется знак подчеркивания _ в названии, так как они и так приватные.

blocTest( 'emits [LoginDataState] after adding email', build: () => bloc, act: (_bloc) => _bloc.add(EditedEmail('example@sample.com')), expect: () => [ isA<LoginDataState>(), ], );

Разве проверки одного только типа состояния достаточно? А вдруг в нем измененный эмейл не сохранится? Или сохранится не тот? Аналогично и в следующем тесте. Вдруг изменение пароля повлияло на ранее сохраненный эмейл?

Тут мы использовали еще одно свойство blocTest - seed, которое нужно для подстановки изначального состояния в BLoC.

Как то использование seed выглядит не очень уместным и даже опасным. По хорошему обычно изолируют зависимости, а в логику тестируемого класса извне не лезут. Другими словами лучше взаимодействовать с тестируемой сущностью только доступными публичными методами. Так как сделано ниже.

blocTest( 'emits [LoginErrorState] if email is null', build: () => bloc, act: (_bloc) { _bloc.add(EditedPassword('myPass123')); _bloc.add(LoginButtonPressed()); }, expect: () => [ isA<LoginDataState>(), isA<LoginLoadingState>(), isA<LoginErrorState>(), ], );

По идее `_bloc.add(EditedPassword('myPass123'));` должно быть в build, так как это относится к части arrange.

Если мы внимательно посмотрим на код, то увидим, что нужно протестировать следующие кейсы:

Наверное так же стоило проверить случаи когда пароль и/или логин неправильные?

Запустил тесты из репозитория, но один не проходит:

package:matcher                              expect
package:mocktail/src/mocktail.dart 595:5     VerificationResult.called
test\auth_bloc\login_bloc_test.dart 93:18    main.<fn>.<fn>
package:bloc_test/src/bloc_test.dart 230:21  testBloc.<fn>
===== asynchronous gap ===========================
dart:async                                   _Completer.completeError
package:bloc_test/src/bloc_test.dart 257:43  _runZonedGuarded.<fn>
===== asynchronous gap ===========================
dart:async                                   _CustomZone.registerBinaryCallback
package:bloc_test/src/bloc_test.dart 254:5   _runZonedGuarded.<fn>
dart:async                                   runZonedGuarded
package:bloc_test/src/bloc_test.dart 253:3   _runZonedGuarded
package:bloc_test/src/bloc_test.dart 200:11  testBloc
package:bloc_test/src/bloc_test.dart 156:13  blocTest.<fn>

Expected: <1>
  Actual: <3>
Unexpected number of calls

Печалька...

if (state.emailStr?.isNotEmpty == false || state.emailStr?.isNotEmpty == false) { emit(LoginErrorState( email: state.emailStr, password: state.passwordStr, errorToShow: 'Email or password is empty', )); return; }

Дважды на пустоту проверяется email, а пароль нет? Странно, что ваши тесты это не отловили. Возможно вам стоит посмотреть в сторону TDD?

Используйте compute функцию: эта функция позволяет кэшировать результаты вычислений, чтобы не повторять их при каждом обновлении экрана.

Функция compute не кэширует результаты.

Спасибо, интересные нюансы. Не знал о них.

Было бы интересно узнать про отличия VCL от FireMonkey. А также плюсы и минусы последнего.

Ну главное, чтобы ребенку нравилось. Смысл идти, если не твое? Ну и если что, вернуться в где можно же?

но не весь спектр задач должен закрываться ими

Согласен.

Автор riverpod уже не однократно говорил, что с релизом макросов, riverpod будет их использовать. Интересно, останется ли возможность использовать riverpod без них? Подозреваю, что нет.

Информация

В рейтинге
Не участвует
Откуда
Россия
Дата рождения
Зарегистрирован
Активность

Специализация

Mobile Application Developer
Senior
Flutter
Flutter Bloc
MobX
Mobile
Development of mobile applications