Pull to refresh
18
0
Журат Максим @ChessMax

User

Send message

Мой первый хард был на 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-ке. Скорее всего поддержку продлят, как это уже было раньше.

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

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

В приведенном примере нет никакой динамической типизации. Рекорды в дарт строго типизированы. Если не указать тип, то компилятор выводит его автоматически. Это называется 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 без них? Подозреваю, что нет.

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity

Specialization

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