Мы успешно применяем KMP. Но вначале очень не нравилась необходимость дублировать обертку ViewModel на iOS. После нескольких итераций мы нашли подход как использовать shared ViewModel без необходимости добавлять обертку.
struct LoginViewScreen: View {
@EnvironmentObject var scopeHolder: NavigationScopeObservable
var body: some View {
let viewModel: LoginViewModel = scopeHolder.scope.login()
ViewWrap(viewModel: viewModel) { $state in
LoginView(
state: $state,
props: LoginViewProps(
onEmailChanged: viewModel.onEmailChanged,
onPasswordChanged: viewModel.onPasswordChanged,
onLogin: viewModel.onLogin,
onNavigateTo: viewModel.onNavigateTo,
onLoginWithBio: viewModel.onLoginWithBio
))
}
}
}
Пробовали ли вы Junie от Jetbrains? У меня есть свой тест для LLM. Беру 1 файл с несложной логикой (код тестируемый) и ввожу 1 prompt `write unit tests`. Не, я конечно могу писать простыни промтов, но нам твердят что LLM заменяют джунов, а джуну `write unit test` было бы достаточно. Сначала всё было плохо, потом стало лучше, но всё равно качественного скачка не было. Приходилось проверять, дописывать, рефакторить, переименовывать файлы и прочее. Приходилось как джуну объяснять code style, naming и прочее. Джун то хоть запоминает. И вот я попробовал Junie ...и произошёл качественный скачок! 1. Был создан новый файл в нужном месте с правильным именем 2. Был использован нужный тестовый фреймворк 3. Был использован тот же подход к замене зависимостей что и в сотне файлов рядом 4. Десяток тестов был запущен, продебажен, исправлен, повторно запущен В итоге не нужно было ни копировать, ни редактировать - только закоммитить. Интересный факт, что мой изначальный промпт был прогнан через LLM и превратился в простыню по которой и была продолжена работа.
Тут есть два варианта: 1. Условный "он" не знает что такое стратегия, точно также он скорее всего не знает эквивалент в виде лямбд и прочей функциональщины. 2. "Он" знает и хочет поменять А на Б. И я знаю чем это закончится. В проекте долгое время будет местами А, местами Б, плюс двойной набор зависимостей, большой техдолг, потому что поменять на Б оказалось местами сложно и "проще переписать с нуля", времени будет потрачено много, а другого не дают. Я, конечно, могу оказаться не прав, но я столько раз оказывался прав да и самую малость умею в риски.
Вы абсолютно правы, однако вы ответили на мой комментарий и я предполагаю на пункт 3. В общем то весь мой комментарий это легкий сарказм. Основной посыл в том, начинающие программисты не понимают работу сеньора и делают выводы. Например, не зная, что такое стратегия кажется очевидным что код запутан, в него намеренно добавлено 10+ классов по <10 строк и всё это легко можно удалить и использовать 10+ switch/case там где надо.
В нашей команде меня называют сеньором, тимлидом и т.д. Именно с меня спрашивает руководство по работе команды. Всё что написано в статье - всё правда.
1. Я дроблю свои таски на субтаски, потому что я предпочитаю потратить час-два на анализ задачи и "на бумаге" её решить. Иногда я это делаю для кого то, но стараюсь не делать. Ведь анализ задачи это часть работы программиста.
2. На встречах чужие задачи у меня часто получают комментарии "Да это очень просто ". Собственно потому что моя задача чтоб все работали, потому беру сложные таски себе. Очень часто это задачи архитектурные, которые часами решаются на бумаге. Я руководствуюсь желанием решить задачу, а не закрыть таск - время исполнения может различаться в разы.
3. Я пишу запутанный код без комментариев. Потому что если разработчику нужна документация к интерфейсу *Стратегия, то ему не стоит делать в этой части правки.
4. Руководство всегда интересуется моим мнением, потому что в прошлом новые разрабы уже проталкивали свои идеи. A я не говорил "я ж говорил" и возвращал проект в стабильность. Потому что на соседнем проекте уже в 4ый что то переделывают (React->Angular, Mongo->SQL, Java->Typescript...). Поиск серебряной пули - знаем, переболели.
5. Я пушу срочно в продакшн. Собственно у меня кнопка, которая запускает билд в прод. Мне доверили прод, я знаю цену ошибки и цену "простоя". Я принимаю решение и если что то срочно ушло в прод без ревью - значит такое было моё решение. Код, кстати в гите.
6. У меня "нет времени" искать способы объяснения которые бы понял именно ты. Я ценю своё время, охотно делюсь опытом. Но это мой опыт, а могу им лишь поделиться, я не могу тебя научить или заставить взять то с чем я делюсь. Мне кажется что вот эта статья хорошо описывает вопрос. Да, вдумчивого чтения на пару часов. Нет, у меня нет видео. Рассказать в двух словах? Так вот же бумага и схема - при тебе рисовал.
7. "Давайте добавим в проект либу А" - скорее всего я отвечу "не надо". Я знаю что эта за либа, я знаю какие аргументы сейчас будут озвучены, я знаю что мои контраргументы будут проигнорированы. Но билд станет больше и дольше, поддержка сложнее, риск поиметь несовместимость и всё это ради экономии 20 строк? Не надо.
Очень много "зашедших в айти", которым BigO уже сложно - они будут жаловаться что я пишу плохой код. Много людей, которые еще до собеседования знали что идут сюда ненадолго - копят техдолг и сваливают в закат. Не мало айтишников, гуру фреймворка ХХХ, который я не знаю, но спотыкаются об очевидный race condition. Я могу быть не прав, но в айти выбор между А и Б чаще всего это как выбор между Windows и Linux и поэтому решать должен опыт, а он у меня есть.
Будет. В примере iOS ViewModel обернут в ObserveableObject, там есть complitionHandler который будет вызываться при обновлении во ViewModel. Значение можно записать в локальную Published переменную. Для каждого VM придется делать обертку в Swift. Мы пошли дальше, унифицировали все VM и используем одну обертку.
Мы используем такой подход: современные браузеры не тормозим, старые и так медленные.
Первым идёт небольшой скрипт который проверяет фичу и синхронно подключает скрипт полифила.
Shadowsocks Золотой щит кроме прямых блокировок занимается анализом траффика и может блокировать любое соединение. Например, если вы делаете dns запросы к facebook, а траффик не идет, то внешнее щифрованное соединение сначало теряет пакеты, а потом может и упасть.Если вы не делаете запросы, например к taobao, но траффик идет, значит вы перенаправили все dns запросы через туннель — опять срабатывает защита. Shadowsocks всё это делит и внутреннее гоняет внутрь, внешнее — через туннель.
Я перепробовал много вариантов, но только через Shadowsocks получилось Youtube в HD. Есть сборка на openwrt — что очень удобно.
Я думаю это лучше, чем «деньги мошенники сняли, в банк позвонить не можем, потому что денег оплатить нет». А вообще при должном планировании ни разу не возникало проблем. В наличности всегда какая то необходимая сумма. Пару раз телефон садился и я просто открывал окно на 2-3 транзакции на пару сотен долларов на несколько часов.
«нет связи» это по моему мнению не аргумент, сейчас гораздо сложнее найти банкомат, чем бесплатный wifi.
У меня есть две карты двух банков, у которых в мобильном приложении есть функция защиты. По умолчанию карта заблокирована. Если нужно снять или оплатить, я должен в приложении указать максимальную сумму, кол-во транзакций и временное окно. Однако возникают сложности с автоплатежами, но для этого у меня другая карта.
Мы успешно применяем KMP. Но вначале очень не нравилась необходимость дублировать обертку ViewModel на iOS. После нескольких итераций мы нашли подход как использовать shared ViewModel без необходимости добавлять обертку.
Пробовали ли вы Junie от Jetbrains?
У меня есть свой тест для LLM. Беру 1 файл с несложной логикой (код тестируемый) и ввожу 1 prompt `write unit tests`. Не, я конечно могу писать простыни промтов, но нам твердят что LLM заменяют джунов, а джуну `write unit test` было бы достаточно. Сначала всё было плохо, потом стало лучше, но всё равно качественного скачка не было. Приходилось проверять, дописывать, рефакторить, переименовывать файлы и прочее. Приходилось как джуну объяснять code style, naming и прочее. Джун то хоть запоминает.
И вот я попробовал Junie ...и произошёл качественный скачок!
1. Был создан новый файл в нужном месте с правильным именем
2. Был использован нужный тестовый фреймворк
3. Был использован тот же подход к замене зависимостей что и в сотне файлов рядом
4. Десяток тестов был запущен, продебажен, исправлен, повторно запущен
В итоге не нужно было ни копировать, ни редактировать - только закоммитить. Интересный факт, что мой изначальный промпт был прогнан через LLM и превратился в простыню по которой и была продолжена работа.
А внутри сеньору можно использовать стратегию?
Тут есть два варианта:
1. Условный "он" не знает что такое стратегия, точно также он скорее всего не знает эквивалент в виде лямбд и прочей функциональщины.
2. "Он" знает и хочет поменять А на Б. И я знаю чем это закончится. В проекте долгое время будет местами А, местами Б, плюс двойной набор зависимостей, большой техдолг, потому что поменять на Б оказалось местами сложно и "проще переписать с нуля", времени будет потрачено много, а другого не дают. Я, конечно, могу оказаться не прав, но я столько раз оказывался прав да и самую малость умею в риски.
Вы абсолютно правы, однако вы ответили на мой комментарий и я предполагаю на пункт 3. В общем то весь мой комментарий это легкий сарказм. Основной посыл в том, начинающие программисты не понимают работу сеньора и делают выводы. Например, не зная, что такое стратегия кажется очевидным что код запутан, в него намеренно добавлено 10+ классов по <10 строк и всё это легко можно удалить и использовать 10+ switch/case там где надо.
В нашей команде меня называют сеньором, тимлидом и т.д. Именно с меня спрашивает руководство по работе команды. Всё что написано в статье - всё правда.
1. Я дроблю свои таски на субтаски, потому что я предпочитаю потратить час-два на анализ задачи и "на бумаге" её решить. Иногда я это делаю для кого то, но стараюсь не делать. Ведь анализ задачи это часть работы программиста.
2. На встречах чужие задачи у меня часто получают комментарии "Да это очень просто ". Собственно потому что моя задача чтоб все работали, потому беру сложные таски себе. Очень часто это задачи архитектурные, которые часами решаются на бумаге. Я руководствуюсь желанием решить задачу, а не закрыть таск - время исполнения может различаться в разы.
3. Я пишу запутанный код без комментариев. Потому что если разработчику нужна документация к интерфейсу *Стратегия, то ему не стоит делать в этой части правки.
4. Руководство всегда интересуется моим мнением, потому что в прошлом новые разрабы уже проталкивали свои идеи. A я не говорил "я ж говорил" и возвращал проект в стабильность. Потому что на соседнем проекте уже в 4ый что то переделывают (React->Angular, Mongo->SQL, Java->Typescript...). Поиск серебряной пули - знаем, переболели.
5. Я пушу срочно в продакшн. Собственно у меня кнопка, которая запускает билд в прод. Мне доверили прод, я знаю цену ошибки и цену "простоя". Я принимаю решение и если что то срочно ушло в прод без ревью - значит такое было моё решение. Код, кстати в гите.
6. У меня "нет времени" искать способы объяснения которые бы понял именно ты. Я ценю своё время, охотно делюсь опытом. Но это мой опыт, а могу им лишь поделиться, я не могу тебя научить или заставить взять то с чем я делюсь. Мне кажется что вот эта статья хорошо описывает вопрос. Да, вдумчивого чтения на пару часов. Нет, у меня нет видео. Рассказать в двух словах? Так вот же бумага и схема - при тебе рисовал.
7. "Давайте добавим в проект либу А" - скорее всего я отвечу "не надо". Я знаю что эта за либа, я знаю какие аргументы сейчас будут озвучены, я знаю что мои контраргументы будут проигнорированы. Но билд станет больше и дольше, поддержка сложнее, риск поиметь несовместимость и всё это ради экономии 20 строк? Не надо.
Очень много "зашедших в айти", которым BigO уже сложно - они будут жаловаться что я пишу плохой код. Много людей, которые еще до собеседования знали что идут сюда ненадолго - копят техдолг и сваливают в закат. Не мало айтишников, гуру фреймворка ХХХ, который я не знаю, но спотыкаются об очевидный race condition. Я могу быть не прав, но в айти выбор между А и Б чаще всего это как выбор между Windows и Linux и поэтому решать должен опыт, а он у меня есть.
Будет. В примере iOS ViewModel обернут в ObserveableObject, там есть complitionHandler который будет вызываться при обновлении во ViewModel. Значение можно записать в локальную Published переменную. Для каждого VM придется делать обертку в Swift. Мы пошли дальше, унифицировали все VM и используем одну обертку.
И это самое худшее что вы вспомнили? Подобные "отрицательные" отзывы для меня всегда были маркером качественного продукта.
Мы используем такой подход: современные браузеры не тормозим, старые и так медленные.
Первым идёт небольшой скрипт который проверяет фичу и синхронно подключает скрипт полифила.
В итоге новый браузер пробегает десяток if и быстро работает, старые браузеры ждут пачки полифилов.
Правда это не работает с async\await и другим новым синтаксисом, но тут мы планируем собирать два бандла.
Я перепробовал много вариантов, но только через Shadowsocks получилось Youtube в HD. Есть сборка на openwrt — что очень удобно.
«нет связи» это по моему мнению не аргумент, сейчас гораздо сложнее найти банкомат, чем бесплатный wifi.
Для навигации по сущностям я использую ctrl + click, первый клик переносит к определению, второй — загружает список всех мест использования.