Вариантов организации структуры проекта куча, нет строго правильного, и часто зависит от конкретных задач. Но после разных экспериментов, мне понравилась вот такая feature-first структура. Это не истина в последней инстанции, но неплохо подойдет в качестве опорной точки, плюс хорошо структурирует понимание существующих частей и их взаимосвязей.
app
Объединяет приложение воедино. Роутинг, сборка зависимостей и обработка ошибок. Слой app потенциально знает обо всех слоях приложения, но при этом остальные слои не знают об app.
core
Общие возможности, которые могут быть использованы в разных частях приложения. Общие компоненты дизайн-системы, утилиты. Любой слой может знать о core, но core не должен знать о других слоях.
data
Обработка сырых данных, API-клиент. Прямая работа с сервером или локальной базой данных. Data-слой может зависеть только от core-слоя.
features
Содержит фичи любого рода. Можно выделить фичи двух видов:
1. Функциональные — фичи без продуктового смысла. Такие фичи не должны зависеть от продуктовых фичей.
2. Продуктовые — фичи, отвечающие за определённую бизнес-логику. Такие фичи могут зависеть от функциональных фичей.
Каждая фича может содержать как только бизнес-специфичные сущности, так и вложенное дробление по слоям data и ui, но обязательно непосредственно связанные с этой фичой.
Знает о существовании data-слоя, но не знает о существовании screens.
screens
Экраны приложения. Могут быть сгруппированы по пользовательским сценариям. Слой screens использует слой features. Допустимо, чтобы screens знал о слое app — через который предоставляется доступ к продуктовым фичам.
Хотя этой связи можно избежать, если использовать Provider/Riverpod или любой другой инструмент прокидывания зависимостей в виджеты.
#tips
app
Объединяет приложение воедино. Роутинг, сборка зависимостей и обработка ошибок. Слой app потенциально знает обо всех слоях приложения, но при этом остальные слои не знают об app.
core
Общие возможности, которые могут быть использованы в разных частях приложения. Общие компоненты дизайн-системы, утилиты. Любой слой может знать о core, но core не должен знать о других слоях.
data
Обработка сырых данных, API-клиент. Прямая работа с сервером или локальной базой данных. Data-слой может зависеть только от core-слоя.
features
Содержит фичи любого рода. Можно выделить фичи двух видов:
1. Функциональные — фичи без продуктового смысла. Такие фичи не должны зависеть от продуктовых фичей.
2. Продуктовые — фичи, отвечающие за определённую бизнес-логику. Такие фичи могут зависеть от функциональных фичей.
Каждая фича может содержать как только бизнес-специфичные сущности, так и вложенное дробление по слоям data и ui, но обязательно непосредственно связанные с этой фичой.
Знает о существовании data-слоя, но не знает о существовании screens.
screens
Экраны приложения. Могут быть сгруппированы по пользовательским сценариям. Слой screens использует слой features. Допустимо, чтобы screens знал о слое app — через который предоставляется доступ к продуктовым фичам.
Хотя этой связи можно избежать, если использовать Provider/Riverpod или любой другой инструмент прокидывания зависимостей в виджеты.
#tips
👍5🔥1
Если начинать Flutter-проект с расчетом, что это будущее полноценное качественное приложение, а не быстрый прототип, то помимо продуктовой продуманности, помните про ряд важных технических моментов, которые стоит учесть как можно раньше, чтобы обеспечить достойный технический уровень проекта прямо со старта. В общем, написал статью для Яндекс Академии с подробным чеклистом, а тут краткое содержание:
1. Настройте проверку качества кода статическим анализатором, aka линтер, aka
2. Подготовьте релизную сборку. Да-да, прямо на старте проекта!
3. Подготовьте окружение и удобные скрипты для автоматической настройки этого окружения. Например, если есть несколько проектов с разными версиями, то fvm — must have.
4. Настройте как минимум Continuous Integration, а хорошо бы и CD.
5. Воспользуйтесь централизованным логгером, благо вариантов на pub.dev достаточно.
6. В корне приложения пропишите централизованную обработку необработанных исключением.
7. Реализуйте интернационализацию. Про отличие от локализации тоже читайте в чеклисте.
8. Опишите централизованную дизайн-тему и UI-компоненты приложения.
#tips
1. Настройте проверку качества кода статическим анализатором, aka линтер, aka
dart analyze. 2. Подготовьте релизную сборку. Да-да, прямо на старте проекта!
3. Подготовьте окружение и удобные скрипты для автоматической настройки этого окружения. Например, если есть несколько проектов с разными версиями, то fvm — must have.
4. Настройте как минимум Continuous Integration, а хорошо бы и CD.
5. Воспользуйтесь централизованным логгером, благо вариантов на pub.dev достаточно.
6. В корне приложения пропишите централизованную обработку необработанных исключением.
7. Реализуйте интернационализацию. Про отличие от локализации тоже читайте в чеклисте.
8. Опишите централизованную дизайн-тему и UI-компоненты приложения.
#tips
education.yandex.ru
Что учесть при разработке мобильного Flutter-приложения: чек-лист
Ваш проект — это не только код. На старте разработки приложения здорово обратить внимание и на другие, не менее важные аспекты, которые сделают проект качественнее и удобнее. Собрали чек-лист вместе с Сергеем Кольцовым, руководителем группы Flutter-разработки…
👌4🤔2
Flutter Bro pinned «Универсальный ответ на вопросы "С чего начать?" и "Как систематизировать знания?": плейлист с лекциями по Flutter от Яндекса. Это сборник из лекций со Школ Мобильной Разработки 2021 и 2022 годов. Лекции сгруппированы по темам и по порядку усложнения. В части…»
Вероятно вы где-нибудь уже слышали, но всё-таки напомню, что летом Яндекс снова запускает Школу Мобильной Разработки!
Подготовка уже кипит во всю, будет топчик, и ещё сегодня в 19:00 на ютубе будет день открытых дверей Школ, залетайте. Ну и регистрируйтесь в саму школу😁
#event
Подготовка уже кипит во всю, будет топчик, и ещё сегодня в 19:00 на ютубе будет день открытых дверей Школ, залетайте. Ну и регистрируйтесь в саму школу
#event
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Школа мобильной разработки 2023 — День открытых дверей
29 марта мы проведём День открытых дверей онлайн, чтобы вы смогли определиться с направлением и задать вопросы о поступлении и обучении. Руководители школ расскажут о программе и отборе, а выпускники прошлых лет поделятся своим опытом, дадут советы будущим…
👍4
Иногда так хочется какой-нибудь дичи, особенно в пятницу вечерком!
Поэтому воспользовался новомодным ChatGPT для самой высокоинтеллектуальной задачи — сгенерировать всратые факты о флаттер-разработчиках.
🧐 Если ты хочешь научиться создавать красивые приложения, следуй за флаттер-разработчиком, но не слишком близко, чтобы не запутаться в его коде.
🧐 Флаттер-разработчик всегда знает, что делать, если приложение начинает вести себя как единорог.
🧐 Флаттер-разработчик не знает, что такое 'отдых', он только знает, что такое 'hot reload'.
🧐 Если вы дадите флаттер-разработчику задание создать приложение за один день, то он напишет его за один час, но только если вы дадите ему две недели.
🧐 Когда флаттер-разработчик устраивает митап, там нет докладчиков, только виджеты, которые приглашены на сцену.
🧐 Флаттер-разработчик может создать приложение, которое будет выглядеть прекрасно, но будет работать как кошмар.
🧐 Если флаттер-разработчик говорит, что знает все о мобильной разработке, то он просто не знает, что не знает.
🧐 Флаттер-разработчик не нуждается в мозгах, у него есть Dart.
Поэтому воспользовался новомодным ChatGPT для самой высокоинтеллектуальной задачи — сгенерировать всратые факты о флаттер-разработчиках.
Please open Telegram to view this post
VIEW IN TELEGRAM
😁10🦄5
Блок и кубит — это сущности для управления состоянием, обе поставляются из пакета bloc. Фундаментально, блок и кубит — это одно и то же — они наследники BlocBase. Это сущность, хранящая в себе состояние и стрим с изменениями этого состояния. И единственный инструмент изменения этого состояния — метод emit. В аргумент методу мы передаём новое состояние, и метод синхронно изменяет его и отправляет в стрим. Отличие блока и кубита лишь в том, как мы будем вызывать метод emit.
Кубит — это, буквально, BlocBase. Следовательно, единственный способ вызывать метод emit — просто напрямую. Но, он protected — значит его можно вызывать только внутри класса или внутри дочерних классов. Поэтому в каждом конкретном кубите мы описываем наши собственные публичные методы с нужным набором аргументов, и уже внутри них вызываем метод emit, чтобы обновить состояние по результатам выполнения.
Блок — это BlocBase на стероидах. Ключевое отличие — в блоке появляется стрим событий. В блоке мы описываем события (базовый класс + дочерние) с набором аргументов и кидаем их в блок через единственный метод add. А логику обработки событий описываем в методах, которые регистрируем в конструкторе блока через метод on. Кайф в том, что этот метод принимает коллбек EventHandler, который может быть асинхронным. И все события, которые попадают в один и тот же обработчик, будут обрабатываться асинхронно, но последовательно, образуя очередь событий. Ну и чтобы обновить состояние блока из EventHandler'а, у него в аргументах есть Emitter, в который мы по готовности закидываем новое состояние.
Короче, что кубит, что блок — это просто класс с мутабельным полем (стейтом) и стримом. В кубите мы обновляем это поле через метод emit, а в блоке — через отправку событий в отдельный стрим, обработка которого происходит в обработчике EventHandler. В нём написана асинхронная логика обновления состояния.
Кубит — это, буквально, BlocBase. Следовательно, единственный способ вызывать метод emit — просто напрямую. Но, он protected — значит его можно вызывать только внутри класса или внутри дочерних классов. Поэтому в каждом конкретном кубите мы описываем наши собственные публичные методы с нужным набором аргументов, и уже внутри них вызываем метод emit, чтобы обновить состояние по результатам выполнения.
Блок — это BlocBase на стероидах. Ключевое отличие — в блоке появляется стрим событий. В блоке мы описываем события (базовый класс + дочерние) с набором аргументов и кидаем их в блок через единственный метод add. А логику обработки событий описываем в методах, которые регистрируем в конструкторе блока через метод on. Кайф в том, что этот метод принимает коллбек EventHandler, который может быть асинхронным. И все события, которые попадают в один и тот же обработчик, будут обрабатываться асинхронно, но последовательно, образуя очередь событий. Ну и чтобы обновить состояние блока из EventHandler'а, у него в аргументах есть Emitter, в который мы по готовности закидываем новое состояние.
Короче, что кубит, что блок — это просто класс с мутабельным полем (стейтом) и стримом. В кубите мы обновляем это поле через метод emit, а в блоке — через отправку событий в отдельный стрим, обработка которого происходит в обработчике EventHandler. В нём написана асинхронная логика обновления состояния.
👍6
Лысый чувак в левом нижнем углу фотографии — это Роман Назаров. Насколько я понял, здесь он впервые услышал про флаттер. Зато он — офигенный тренер по публичным выступлениям. На ютубе у него есть гигантский трехчасовой прямой эфир по подготовке к публичным выступлениям, ну или есть часовая лекция поменьше, если вы очень торопитесь.
А ещё на этой фотке есть я — рассказываю чистовой прогон своего доклада Роману. Потому что через 2 недели, 22 апреля, команда Яндекс Go и Яндекс Pro проведёт большую конференцию по мобильной разработке! И там целый трек будет посвящен Flutter-разработке. Ну и я тоже там докладываюсь.
Конференция будет оффлайн в Москве и без live-трансляции, поэтому если у вас есть возможность поприсутствовать физически — срочно регистрируйтесь вот прям щас! Потому что количество мест ограничено. А конфа будет космическая, уж поверьте😎
А когда придёте на конфу — ловите меня после доклада, поболтаем🙃
#event
А ещё на этой фотке есть я — рассказываю чистовой прогон своего доклада Роману. Потому что через 2 недели, 22 апреля, команда Яндекс Go и Яндекс Pro проведёт большую конференцию по мобильной разработке! И там целый трек будет посвящен Flutter-разработке. Ну и я тоже там докладываюсь.
Конференция будет оффлайн в Москве и без live-трансляции, поэтому если у вас есть возможность поприсутствовать физически — срочно регистрируйтесь вот прям щас! Потому что количество мест ограничено. А конфа будет космическая, уж поверьте
А когда придёте на конфу — ловите меня после доклада, поболтаем
#event
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤2👍2🤩1💩1
Последние 2 недели были насыщены активностями, поэтому писать что-то сюда сил уже не хватало. Зато мы провели офигенный интенсив в Сириусе по флаттеру и iOS, а сразу после него — конфу по мобилке от Яндекс Go.
Поэтому, чтобы вы меня не совсем теряли, держите напоминание: уже ровно через 2 недели пройдет Google I/O, так что не забывайте регистрироваться. Будем надеяться, что генеративные нейросетки не займут весь эфир и флаттеру тоже достанется🫥
Поэтому, чтобы вы меня не совсем теряли, держите напоминание: уже ровно через 2 недели пройдет Google I/O, так что не забывайте регистрироваться. Будем надеяться, что генеративные нейросетки не займут весь эфир и флаттеру тоже достанется
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤6🔥3
В Dart очень изящно избавились от ключевого слова interface, а теперь снова его добавляют (и, на мой взгляд, не зря). Но независимо от его наличия/отсутствия мне всегда немножко грустно от избыточного использования сущности интерфейсов в любой непонятной ситуации. Потому что пользы это не добавляет, зато добавляет много бесполезного кода, который точно никогда не пригодится.
В дарте любой класс — это уже неявный интерфейс. Поэтому по умолчанию у класса уже есть интерфейс, его не нужно писать дополнительно! А выделять в отдельный класс-интерфейс его имеет смысл в трех случаях:
1. Когда есть несколько реализаций одного и того же публичного API класса.
2. Когда у реализации публичный интерфейс для “потребителя” шире, чем для внутреннего использования, и его нужно сузить.
3. Когда реализации в принципе не существует и её должен написать сам "потребитель".
И вот ещё статейка на эту тему (правда не про Dart).
В дарте любой класс — это уже неявный интерфейс. Поэтому по умолчанию у класса уже есть интерфейс, его не нужно писать дополнительно! А выделять в отдельный класс-интерфейс его имеет смысл в трех случаях:
1. Когда есть несколько реализаций одного и того же публичного API класса.
2. Когда у реализации публичный интерфейс для “потребителя” шире, чем для внутреннего использования, и его нужно сузить.
3. Когда реализации в принципе не существует и её должен написать сам "потребитель".
И вот ещё статейка на эту тему (правда не про Dart).
👍6🔥6⚡3
Пятничный серьезный пост про Google I/O
Google I/O состоялся, там объявили о релизах и рассказали про новые возможности в Dart 3 и в Flutter 3.10. Почитать про них вы можете и в приведенных статьях, а вот про секретные неанонсированные возможности вы нигде, кроме как тут, не узнаете! Итак, вот они:
Dart 3
👩💻 Добавлены ключевые слова
👩💻 Теперь в Dart есть ключевое слово
👩💻 Введен новый оператор
👩💻 Dart теперь позволяет использовать магические заклинания вместо ключевых слов, которые упрощают синтаксис и делают код более читабельным. Например, вместо
👩💻 Добавлена возможность создавать асинхронные функции, которые работают только по выходным дням.
👩💻 Введена функция
👩💻 Появился новый модификатор доступа
👩💻 Добавлен оператор
👩💻 Добавлен модификатор
👩💻 Dart 3.0 теперь позволяет программистам использовать печенье вместо переменных.
Flutter 3.10
👩💻 Теперь для создания кнопок в Flutter нужно использовать не
👩💻 Flutter 3.10 позволяет создавать анимации с помощью жестов тела, включая танцы.
👩💻 Теперь вы можете использовать
👩💻 Flutter 3.10 позволяет создавать пользовательский интерфейс, который изменяется в зависимости от фазы луны.
👩💻 В Flutter 3.10 появился новый виджет "Кричащий текст", который автоматически изменяет размер шрифта, чтобы привлечь внимание пользователя. Доступен только в ярко-розовом цвете.
👩💻 Добавлен новый виджет
👩💻 В Flutter появился виджет
👩💻 В Flutter 3.10 добавлена новая опция для виджетов "невидимое нажатие", которая позволяет пользователям нажимать на несуществующие элементы экрана.
👩💻 Flutter добавил новый виджет для создания духовных мантр под названием
👩💻 В Flutter 3.10 появилась новая функция
Да, это ChatGPT сгенерировал
Google I/O состоялся, там объявили о релизах и рассказали про новые возможности в Dart 3 и в Flutter 3.10. Почитать про них вы можете и в приведенных статьях, а вот про секретные неанонсированные возможности вы нигде, кроме как тут, не узнаете! Итак, вот они:
Dart 3
maybe, probably, и who-knows для более точного описания неопределенных переменных. sarcasm, которое позволяет писать саркастический код, который будет компилироваться только в случае, если в вашей команде есть программисты с достаточным уровнем чувства юмора. ??!, который выбрасывает случайное исключение. if можно написать abra cadabra. magic(), которая автоматически исправляет все ошибки в коде, используя магию. invisible, который делает переменную невидимой для всех, кроме тебя. maybeNull, который возвращает null с вероятностью 50%. awesome, который делает функцию более крутой. Flutter 3.10
ElevatedButton и не TextButton, а EmojiButton и GifButton. FlutterTeleportation для перемещения виджетов из одного места в другое без анимации! FlutterSocialDistancer, который автоматически раздвигает элементы UI на безопасное расстояние друг от друга. MemeGenerator, который автоматически создает мемы на основе данных, полученных от пользователя. PrayerWidget, который позволяет пользователям создавать свои собственные мантры и повторять их в своих приложениях. shakePhone(), которая вызывает случайные вибрации на устройстве пользователя.Please open Telegram to view this post
VIEW IN TELEGRAM
😁15🤣8🫡2💩1👻1
Вот вам любопытная задачка. Какой будет результат выполнения?
Насторожились из-за
Короче, две не самые очевидные вещи, которые можно взять из этого кода:
1. Асинхронная функция выполняется синхронно до первого встреченного await, т.е. весь синхронный код выполняется сразу же.
2. Если вам нужно осознанно обойти это поведение и заставить ваш синхронный код внутри асинхронной функции сразу уйти на следующую итерацию Event Loop'а — конструкция
Ну и ссылочка на почитать про async/await. Ну и ответ:
A - main - microA - B
void main() {
a();
b();
print('main');
}
Future<void> a() async {
print('A');
await Future.microtask(() => print('microA'));
}
Future<void> b() async {
await null;
print('B');
}
Насторожились из-за
await null? А первым у вас выводится "main" или "A"?Короче, две не самые очевидные вещи, которые можно взять из этого кода:
1. Асинхронная функция выполняется синхронно до первого встреченного await, т.е. весь синхронный код выполняется сразу же.
2. Если вам нужно осознанно обойти это поведение и заставить ваш синхронный код внутри асинхронной функции сразу уйти на следующую итерацию Event Loop'а — конструкция
await null внезапно считается вполне каноничным вариантом.Ну и ссылочка на почитать про async/await. Ну и ответ:
👍7🔥3✍2💩2🌭2👨💻2😱1
Всем привет, я тут немношк пропал из-за отпуска, но зато теперь принёс вам сразу две классные штуки (и кучу ссылок).
Первая классная штука: выложили видео с нашей конференции Go Mobile. Конечно же обязательно смотрите мой доклад про то, как мы пишем полсотни приложений (это даже почти не байт).
Но вообще все доклады крутые:
1. Про важность понимания натива во флаттере
2. Про переход на Flutter от руководителей разных команд
3. Про настройку собственного pub сервера и зачем это нужно
Вторая классная штука: завтра (8 июня) в 19:00 по Москве я прямо лайв буду читать первую лекцию нашего открытого лектория Школы Мобильной Разработки по направлению Flutter. Немножко расскажу про текущее состояние дел флаттера, плюс по классике небольшое повторение базы.
Ну и в целом вот весь открытый лекторий, там ещё пачка разных направлений — записывайтесь и зовите друзей💃
Первая классная штука: выложили видео с нашей конференции Go Mobile. Конечно же обязательно смотрите мой доклад про то, как мы пишем полсотни приложений (это даже почти не байт).
Но вообще все доклады крутые:
1. Про важность понимания натива во флаттере
2. Про переход на Flutter от руководителей разных команд
3. Про настройку собственного pub сервера и зачем это нужно
Вторая классная штука: завтра (8 июня) в 19:00 по Москве я прямо лайв буду читать первую лекцию нашего открытого лектория Школы Мобильной Разработки по направлению Flutter. Немножко расскажу про текущее состояние дел флаттера, плюс по классике небольшое повторение базы.
Ну и в целом вот весь открытый лекторий, там ещё пачка разных направлений — записывайтесь и зовите друзей
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13❤4⚡1🤡1🤗1
В недрах флаттер-трека Школы Мобильной Разработки всплыл вечный спор за/против GetX. Решил пересмотреть легендарный баттл по этому поводу, а потом ещё наткнулся на закреп в одном из чатиков по флаттеру. Ну и, так как я свою сторону уже давно выбрал, держите небольшую выжимку из этих источников на тему "почему GetX — это плохо":
1. Переизобретает и копирует как сам флаттер, так и другие устойчивые пакеты, заточенные под разные задачи. MaterialApp, http, ChangeNotifier, стримы, MobX, GetIt и ещё массу других инструментов.
2. Нарушает буковки из SOLID; лишен абстракций и расширяемости; протекает доступ к внутренним методам; использует и поощряет антипаттерны; противоречит парадигмам, диктуемым флаттером; слабая (а иногда и "чересчур приукрашивающая") документация; нарушения кодстайла флаттера и дарта.
3. Работает хуже аналогов. Хуже перфоманс, больше багов, минимум тестов. GetX пытается быть всем и сразу, но получается у него строго хуже, чем у конкретных инструментов для конкретных задач.
4. GetX — это абстракция над абстракцией. Из-за этого чисто GetX-разработчика сложно назвать Flutter-разработчиком, потому что при использовании GetX от флаттера в коде практически не остается и следа.
5. Жесткий vendor lock. По итогу всё ваше приложение пронизано фреймворком, чего (при правильном использовании) не позволяет себе даже флаттер. При этом огромное количество копирования и дублирования вкупе с наличием всего одного главного ментейнера даёт очень высокие риски остаться с неподдерживаемым инструментом в вашем проекте.
Единственная причина, хоть как-то оправдывающая использование GetX — возможность сверхбыстро наклепать прототип, который в будущем обязательно нужно выбросить и переписать с нуля.
И давайте договоримся, что эмоджи какашки под этим постом будет означать “Мне НЕ нравится GetX!”.
1. Переизобретает и копирует как сам флаттер, так и другие устойчивые пакеты, заточенные под разные задачи. MaterialApp, http, ChangeNotifier, стримы, MobX, GetIt и ещё массу других инструментов.
2. Нарушает буковки из SOLID; лишен абстракций и расширяемости; протекает доступ к внутренним методам; использует и поощряет антипаттерны; противоречит парадигмам, диктуемым флаттером; слабая (а иногда и "чересчур приукрашивающая") документация; нарушения кодстайла флаттера и дарта.
3. Работает хуже аналогов. Хуже перфоманс, больше багов, минимум тестов. GetX пытается быть всем и сразу, но получается у него строго хуже, чем у конкретных инструментов для конкретных задач.
4. GetX — это абстракция над абстракцией. Из-за этого чисто GetX-разработчика сложно назвать Flutter-разработчиком, потому что при использовании GetX от флаттера в коде практически не остается и следа.
5. Жесткий vendor lock. По итогу всё ваше приложение пронизано фреймворком, чего (при правильном использовании) не позволяет себе даже флаттер. При этом огромное количество копирования и дублирования вкупе с наличием всего одного главного ментейнера даёт очень высокие риски остаться с неподдерживаемым инструментом в вашем проекте.
Единственная причина, хоть как-то оправдывающая использование GetX — возможность сверхбыстро наклепать прототип, который в будущем обязательно нужно выбросить и переписать с нуля.
И давайте договоримся, что эмоджи какашки под этим постом будет означать “Мне НЕ нравится GetX!”.
💩32🤡5❤4👍2🔥2👌2💯2😎1
У Сёрфов дропнулся свежий пост про версионирование, а я давно подумывал написать про эту тему, так что идеальнее момента придумать сложно. Для контекста стоит прочитать их пост, там есть необходимая теория, а я сделаю несколько, на мой взгляд, важных дополнений.
Проблема: если при объявлении зависимостей вы используете "шапочку" (caret syntax), то при вызове
Ребята предлагают решать это радикально — не использовать шапочку и жестко связывать все зависимости руками. Тогда
А описанная проблема решается так — в проект приложения коммитится pubspec.lock. Так нужно делать. Об этом прям курсивом сказано в документации, вот тут в последнем абзаце. Всё, вы восхитительны и вызов
Ежели вы пишете не приложение, а пакет, то вы обязаны использовать "шапочку", иначе вашим пакетом будет невозможно пользоваться — наличие его в проекте как ломом заклинит все версии зависимых пакетов и они просто не будут резолвиться, если эти же пакеты есть в самом проекте-потребителе и их версии отличаются от ваших. И в этом случае правильно — не коммитить pubspec.lock. Это обязывает вас проверять свой пакет на самых свежих версиях зависимостей, потому что ваши пользователи потенциально будут использовать их в связке с вашим пакетом.
Ну и использовать dependency_overrides — это как держать паяльник за стержень, потому что так удобнее и даёт вам больше контроля над процессом. dependency_overrides — это инструмент для исключительных кейсов, когда зависимости по каким-то причинам не имеют пересекающихся констрейнтов — а это всегда не очень хорошая ситуация и всегда связано с риском огрести несовместимость интерфейсов и вообще не собрать проект.
Короче, чтобы подробнее разобраться в теме:
1. Прочитайте внимательно доку (все ссылки выше).
2. Посмотрите видосик с последнего Google I/O.
3. Посмотрите свежую лекцию с ШМР.
4. И пользуйтесь инструментом так, как это задумано его конструкцией.
Проблема: если при объявлении зависимостей вы используете "шапочку" (caret syntax), то при вызове
flutter pub get версия таких зависимостей может обновляться автоматически вплоть до ближайшего мажора. А это мало того, что неявно, так ещё и разработчики этих библиотек могут ненароком сломать совместимость даже в рамках текущего мажора.Ребята предлагают решать это радикально — не использовать шапочку и жестко связывать все зависимости руками. Тогда
pub get никогда не сделает что-то самовольно. Это было бы хорошим решением, если бы не ломало всю концепцию версионирования по констрейнтам — давать графу зависимостей гибкость при изменении версий.А описанная проблема решается так — в проект приложения коммитится pubspec.lock. Так нужно делать. Об этом прям курсивом сказано в документации, вот тут в последнем абзаце. Всё, вы восхитительны и вызов
flutter pub get никогда ничего вам самовольно не обновит.Ежели вы пишете не приложение, а пакет, то вы обязаны использовать "шапочку", иначе вашим пакетом будет невозможно пользоваться — наличие его в проекте как ломом заклинит все версии зависимых пакетов и они просто не будут резолвиться, если эти же пакеты есть в самом проекте-потребителе и их версии отличаются от ваших. И в этом случае правильно — не коммитить pubspec.lock. Это обязывает вас проверять свой пакет на самых свежих версиях зависимостей, потому что ваши пользователи потенциально будут использовать их в связке с вашим пакетом.
Ну и использовать dependency_overrides — это как держать паяльник за стержень, потому что так удобнее и даёт вам больше контроля над процессом. dependency_overrides — это инструмент для исключительных кейсов, когда зависимости по каким-то причинам не имеют пересекающихся констрейнтов — а это всегда не очень хорошая ситуация и всегда связано с риском огрести несовместимость интерфейсов и вообще не собрать проект.
Короче, чтобы подробнее разобраться в теме:
1. Прочитайте внимательно доку (все ссылки выше).
2. Посмотрите видосик с последнего Google I/O.
3. Посмотрите свежую лекцию с ШМР.
4. И пользуйтесь инструментом так, как это задумано его конструкцией.
👍19❤2
Добрался почитать результаты опроса Q1 2023 от Flutter team. Краткий пересказ, если ещё не успели ознакомиться:
1. 93% разрабов (здесь и далее — среди тех, кто прошёл опрос) довольны флаттером, из них половина — очень довольны.
2. На 24% увеличилось количество флаттер-разработчиков.
3. И Flutter-разрабы по результатам опроса, и Flutter team по своим метрикам сходятся во мнении, что флаттер растет очень быстро.
4. Те, кто не согласен с этим мнением, в основном аргументируют это отсутствием вакансий/кандидатов, либо отсутствием примеров внедрения Flutter в крупных компаниях.
5. Половина разрабов столкнулись с той или иной миграцией за последний год из-за breaking changes, 44% разрабов грустили и страдали по этому поводу, однако больше 60% сказали, что код стал чище и вообще изменения полезные.
6. В ответ на это Flutter team пообещала делать меньше ломающих изменений, т.к. флаттеру пора взрослеть изаводить семью становиться устойчивым в том числе и в плане API.
7. Firebase Dynamic Links закапывают в пользу нативных App Links и Universal Links, но на миграцию будет минимум 12 месяцев. Особенно забавно этот пункт выглядит, если перечитать предыдущий.Но на самом деле они ж не виноваты, это всё Firebase .
1. 93% разрабов (здесь и далее — среди тех, кто прошёл опрос) довольны флаттером, из них половина — очень довольны.
2. На 24% увеличилось количество флаттер-разработчиков.
3. И Flutter-разрабы по результатам опроса, и Flutter team по своим метрикам сходятся во мнении, что флаттер растет очень быстро.
4. Те, кто не согласен с этим мнением, в основном аргументируют это отсутствием вакансий/кандидатов, либо отсутствием примеров внедрения Flutter в крупных компаниях.
5. Половина разрабов столкнулись с той или иной миграцией за последний год из-за breaking changes, 44% разрабов грустили и страдали по этому поводу, однако больше 60% сказали, что код стал чище и вообще изменения полезные.
6. В ответ на это Flutter team пообещала делать меньше ломающих изменений, т.к. флаттеру пора взрослеть и
7. Firebase Dynamic Links закапывают в пользу нативных App Links и Universal Links, но на миграцию будет минимум 12 месяцев. Особенно забавно этот пункт выглядит, если перечитать предыдущий.
👍4👌4❤1
Держите пятничный анекдот:
В одной IT компании долгие годы работал один старый flutter разработчик. Перед началом каждого рабочего дня он доставал из ящичка в своем столе бумажку, читал ее и убирал назад. После его ухода на пенсию, все сотрудники кинулись смотреть, что же написано в той бумажке. Разворачивают, а там "--no-sound-nullsafety — без налсейфти, flutter pub run build_runner build --delete-conflicting-outputs --verbose — запустить кодген "
Кстати, автор этого анекдота Никита — позавчера рассказывал лекцию в ШМР про девтулзы во флаттере.
В одной IT компании долгие годы работал один старый flutter разработчик. Перед началом каждого рабочего дня он доставал из ящичка в своем столе бумажку, читал ее и убирал назад. После его ухода на пенсию, все сотрудники кинулись смотреть, что же написано в той бумажке. Разворачивают, а там "
Кстати, автор этого анекдота Никита — позавчера рассказывал лекцию в ШМР про девтулзы во флаттере.
🤣20👍7😁3🤮1🤡1🙈1
Я ещё молодой, шутливый, поэтому вскрою одну тему. Что правильнее: кидать исключения или возвращать Either?
Коротко про суть: исключения основаны на "бросании" (throw) и "перехватывании" (catch) ошибок во время выполнения, минуя возвращаемое значение. Either — это и есть возвращаемое значение, которое явно содержит два возможных результата: ошибка (left) или успех (right). Иногда используют Result(ok, error).
Несколько раз в рабочих чатах разгоралась эта тема, поэтому я решил перечитать аргументы обеих сторон и выделил ключевые.
Исключения
➕ Не нужен дополнительный класс/библиотека, от которых будет зависеть вся кодовая база, потому что исключения — это встроенный механизм языка.
➕ Сохраняется полная цепочка методов из стектрейса, можно от и до проследить, кто-кого-откуда вызвал и упал.
➖ Неявное ветвление кода из-за неожиданных исключений ухудшает понимание потока программы. А это может усложнить отладку и тестирование.
Either
➕ Обязывает обработать возвращаемое значение на уровне компиляции как в случае успеха, так и в случае ошибки.
➕ Есть удобные утилитарные методы для обработки результата, типа map/flatMap/fold.
➖ Ухудшает читаемость кода: обрабатывать оба сценария (успех и ошибку) нужно в каждом методе, что нагромождает логику. Проще читать код, когда нормальный процесс работы приложения описан в одном месте, а обработка ошибок — в другом.
Вот ещё несколько статей и обсуждений (в том числе в комментариях) на эту тему с аргументами как за, так и против:
- Тип данных Either как альтернатива выбрасыванию исключений
- Either vs Exception Handling
- Обсуждение на StackOverflow
Предлагаю голосовать: кому что ближе?
Коротко про суть: исключения основаны на "бросании" (throw) и "перехватывании" (catch) ошибок во время выполнения, минуя возвращаемое значение. Either — это и есть возвращаемое значение, которое явно содержит два возможных результата: ошибка (left) или успех (right). Иногда используют Result(ok, error).
Несколько раз в рабочих чатах разгоралась эта тема, поэтому я решил перечитать аргументы обеих сторон и выделил ключевые.
Исключения
Either
Вот ещё несколько статей и обсуждений (в том числе в комментариях) на эту тему с аргументами как за, так и против:
- Тип данных Either как альтернатива выбрасыванию исключений
- Either vs Exception Handling
- Обсуждение на StackOverflow
Предлагаю голосовать: кому что ближе?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6👨💻3❤1👻1
Вышел новый выпуск Flutter Dev Podcast про FlutterFlow.
Про него я знаю уже давно, но руки не доходили попробовать. Но тут послушал подкаст и решил устроить себе челлендж — максимально быстро сделать простенькое приложениеиз говна и палок на No-Code.
Взял идею, которую часто даю студентам как первую домашку: есть открытая апишка — chucknorris.io — она возвращает рандомную шутку о Чаке Норрисе. Задача — сделать тиндер с такими шутками. Ну или хотя бы отображать одну шутку на экране и обновлять её по нажатию на кнопку.
Я сразу зачем-то решил делать свайпающиеся карточки (ну а чо, там был готовый элемент!), ничего не вышло, я забил, решил сделать хотя бы просто загрузку ОДНОЙ шутки на инициализации, тоже сходу не получилось, но к тому моменту я уже провозился целый час и мне стало очень жалко этот час, поэтому я категорически забил, чтобы потом не очнуться в полночь с жоским чувством вины за продолбанную субботу.
Выводы
1. Даже No-Code — это всё ещё новый инструмент, с которым нужно разбираться. Я вот достаточно много времени потратил просто на то, чтобы понять, где я вообще. Документацию я конечно же не читал, иначе какой это челлендж. Но я уверен, что если сесть возиться в следующий раз, то будет уже сильно проще.
2. Возможно плохо искал, но я не нашел инструментов для дебага. Вот если у меня приложениетупа не работает ведет себя не так, как я ожидаю — мне как понять, что именно я сделал не так?! Цените ваши дабеггеры, девтулзы и конечно же логгер, пацаны и пацанессы.
3. Оправдываюсь первыми пунктами, надеясь, что это не я просто тупой.
Спасибо сёрфам за мотивационный пинок, хоть попробовал, кто такой этот ваш FlutterFlow.
Про него я знаю уже давно, но руки не доходили попробовать. Но тут послушал подкаст и решил устроить себе челлендж — максимально быстро сделать простенькое приложение
Взял идею, которую часто даю студентам как первую домашку: есть открытая апишка — chucknorris.io — она возвращает рандомную шутку о Чаке Норрисе. Задача — сделать тиндер с такими шутками. Ну или хотя бы отображать одну шутку на экране и обновлять её по нажатию на кнопку.
Я сразу зачем-то решил делать свайпающиеся карточки (ну а чо, там был готовый элемент!), ничего не вышло, я забил, решил сделать хотя бы просто загрузку ОДНОЙ шутки на инициализации, тоже сходу не получилось, но к тому моменту я уже провозился целый час и мне стало очень жалко этот час, поэтому я категорически забил, чтобы потом не очнуться в полночь с жоским чувством вины за продолбанную субботу.
Выводы
1. Даже No-Code — это всё ещё новый инструмент, с которым нужно разбираться. Я вот достаточно много времени потратил просто на то, чтобы понять, где я вообще. Документацию я конечно же не читал, иначе какой это челлендж. Но я уверен, что если сесть возиться в следующий раз, то будет уже сильно проще.
2. Возможно плохо искал, но я не нашел инструментов для дебага. Вот если у меня приложение
3. Оправдываюсь первыми пунктами, надеясь, что это не я просто тупой.
Спасибо сёрфам за мотивационный пинок, хоть попробовал, кто такой этот ваш FlutterFlow.
👨💻8😁3🥴3👏2💩2👍1🤓1
А вот и результат работы двух десятков людей из нескольких команд: Flutter Handbook!
Вся команда постаралась на славу, такие все котики!😇
Читайте сами и делитесь с друзьями, кто заглядывается на флаттер, но всё никак не решится. И делитесь впечатлениями в группе в телеге!
А мы продолжим развивать хэндбук и делать его ещё круче 😎
Вся команда постаралась на славу, такие все котики!
Читайте сами и делитесь с друзьями, кто заглядывается на флаттер, но всё никак не решится. И делитесь впечатлениями в группе в телеге!
А мы продолжим развивать хэндбук и делать его ещё круче 😎
Please open Telegram to view this post
VIEW IN TELEGRAM
education.yandex.ru
Flutter — Хендбук от Яндекс Образования
Этот хендбук позволит вам разобраться в устройстве Flutter, особенностях его компонентов, языке Dart и паттернах проектирования современных приложений
🔥29❤6👏2❤🔥1🎉1
Можете официально считать это фишкой канала: когда мне лень некогда писать полезные посты, я просто прошу ChatGPT сгенерить какую-нибудь дичь на тему флаттера.
На этот раз всратые советы по написанию кода:
☝️ Переменные, объявленные внутри StatefulWidget, должны быть объявлены с приставкой "внутри_".
☝️ Если вы хотите использовать async/await в Flutter, то вы должны совершить жертвоприношение в виде некоторого количества капель крови каждый раз, когда используете эту конструкцию.
☝️ Никогда не делайте бэкапы своего кода на Dart и Flutter. Это займет слишком много места на вашем жестком диске, а вам все равно не пригодится.
☝️ Если вам нужно протестировать свой код на Flutter, сделайте это на живом питоне. Никаких виртуальных машин и эмуляторов - только настоящий змей.
☝️ Для того, чтобы гарантировать эффективность вашего кода, каждый аргумент функции должен иметь уникальный идентификатор, который был сгенерирован на основе вашего хронотипа.
☝️ Если ты пишешь на Dart, то всегда начинай свой код со слов "import 'dart:math';", чтобы дать своей программе более математический характер.
☝️ Если ты пишешь на Dart, то всегда используй const, даже когда это не имеет смысла, чтобы показать свое уважение к памяти и оптимизации.
А ещё завтра выступаю на Стачке в Ульяновске, так что если вы внезапно тоже там будете — ловите в местах, где базарят за флаттер.
На этот раз всратые советы по написанию кода:
А ещё завтра выступаю на Стачке в Ульяновске, так что если вы внезапно тоже там будете — ловите в местах, где базарят за флаттер.
Please open Telegram to view this post
VIEW IN TELEGRAM
😁13🦄6🔥4🌭2✍1💩1