Pull to refresh
24
0
Ивлев Александр @ivlevAstef

Senior/Lead iOS software developer

Send message

Я побуду занудой, но последний пример shuffle функции, является не валидным. На многих языках он не приведет к печальным последствиям, но на С++ похожий код может привести к крашу.

А все почему? Так-как нарушено правило: если a > b, то b < a. Ну и а == а, и транзитивность, и...

На всякий открыл какую-то документацию по JavaScript и нашел там целый список правил:

  • Stable: The comparator returns the same result with the same pair of input.

  • Reflexive: compareFn(a, a) === 0.

  • Anti-symmetric: compareFn(a, b) and compareFn(b, a) must both be 0 or have opposite signs.

  • Transitive: If compareFn(a, b) and compareFn(b, c) are both positive, zero, or negative, then compareFn(a, c) has the same positivity as the previous two.

JavaScript в общем не исключение из правил.

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

И опять же - а можно не валидный код называть красивым? Но это больше философский вопрос. Квадратный корень в квейке считается не валидно, а приближенно, но многие пример назовут красивым.

Как iOS разработчик вообще не понимаю любовь к даггеру. Когда делал свою DI либу я многие языки рассматривал и как у них реализованы DI либы... И даггер в списке был на последнем месте по удобству и понятности... В. Списке лучших оказался autofac из C#.

Это из той серии когда модный дизайнер сказал что эта одежда будет модой X года, и подумаешь она не удобная - зато модная.

За статью спасибо, ещё раз убедился, что не только мне dagger не нравится ?

Интересно - сколько времени было потрачено на конкурс? Возможно приблизительно.

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

Хорошая статья. Написана простым языком - вроде читаешь про сложные вещи, но всё понятно.

Давно хотел узнать как в Swift происходит всё это, и теперь есть понимание.

Для себя подметил важный момент про то, что даже если объект уничтожен, память под него может быть выделена ещё, долгое время.

Буду ждать продолжения :)

Я уже использую SPM около года, но после статьи я не понял зачем он мне? Недостатки описаны, а плюсы как-то не очень...


Я бы ещё добавил в недостатки — в xcode при создание файла для пакета нельзя настроить шаблон, из-за чего header приходиться писать ручками каждый раз.


И отмечу, что многие недостатки можно решить проще сделав всеже xcode проект, и включив в него корневой SPM модуль который подгрузит остальные. Тем более до недавнего времени это был единственный способ добавить ресурсы.


Cocoapods зависимости можно решить тем же путём (xcframework тоже хорошо, но это усложняет процесс развертки проекта). Правда, если cocoapods добавить в проект, то SPM модули не смогут использовать зависимость. Это как минус — нужно писать обёртку/протоколы, так и плюс — отсутствие прямой зависимости на стороннюю библиотеку.


За статью спасибо — с этими проблемами сам сталкивался и решал похожим образом. Особенно всегда хорошо дополнительные материалы по xcframework — без Гугла пересобрать обычный framework в xcframework я на память не смогу :)

Спасибо. Извиняюсь за свою наглость, но посмотрев профайлером код, оказалось, что столь низкие показатели следствие бага (в последних версиях), а не глобальный косяк.


Если будет лишняя минутка то я был бы рад, обновлению диаграммы (можно даже двух) с версией библиотеки 4.2.0 (а то совсем стыдно за текущую). Так как у меня после исправления, цифры на resolve получаются на много лучше (в 6-7 раз).


Я кстати еще заметил один нюанс (который не сильно сказывается на общую картину, но всеже). Тесты проводятся в дебаг режиме, а как по мне производить тесты скорости правильнее в релиз — там всеже оптимизации включаются, и различные дебаг вещи выключаются.


P.S. Но в любом случае, статья завела механизм — теперь перепишу код, чтобы просто стать не в конкуренции в плане производительности :)


P.P.S. У себя я тестировал в debug/release и iphone XR и SE. Кое где даже быстрее swinject.

Как уже писали выше — xamarin на самом деле популярен. Среди заказных приложений. И react native тоже был, но Facebook сам от него отказался.
Первые версии xamarin были багованные, особенно я помню как я играл в игру — оттебаж за 5 секунд.


Но плюс xamarin всегда был в том, что он позволял писать и отдельно под каждую платформу и что-то объединять при этом. И это на самом деле удобно, и не сильно сложно.


Я конечно не пользуюсь xamarin сейчас, но ребята из KMM идут близко к его пути. И мне кажется нишу они займут туже, что и xamarin.


А как я говорю лучшая кроссплатформа это С++, если не одно но — С++. Способ интеграции и взаимодействия достаточно удобен (особенно если djinni), код можно дебажить, нет багов. Один минус — ну писать бизнес логику на С++ в 21 веке… Ну уж нет — язык сложный, ещё и буковок много.

Небольшое замечание:


  • DITranqullity использует prototype
  • Swinject использует transient
  • Dip использует shared, а аналог это unique
  • EasyDI использует по умолчанию, не знаю какой это, но prototype закометирован.

Это по поводу injection зависимостей. А на них это важно — одно дело создать 10 объектов всего, другое создать порядка 50 :) и тут явно DIP выбивается.


Для TestClass не так критично, но для корректности конечно тоже лучше одинаковый scope.


P.S. при желании можно тест расширить и сделать два графика (prototype/objectGraph). И мне кажется objectGraph более приближенно к реальности будет — prototype не так часто используется, особенно когда несколько ссылок.

Ай извиняюсь. Ссылки то я и пропустил… Всё вопрос отпал. Ещё раз спасибо за статью

Спасибо за статью. Особенно с сравнения.


Посмотрел на второй график. Походу надо снова оптимизировать. Уже давно хочу. С появлением отложенных внедрений сильно всё замедлилось внутри (до них обгонял swinject даже на простых кейсах с маленьким количеством).


Но всеравно вопрос, что именно во втором тесте было? Можно получить пример кода? Он будет отличной отправной точкой и performance тестом при оптимизации ядра.


А то все эти lazy, provide, many, arg, tag слишком много времени отъедают даже если не используются. А именно они самые долгие — as/is очень дорогие операции.

Достаточно подробно описано как делать, за что плюс.
Я каждый раз когда создаю framework ручками трачу на это час… Ибо пока вспомнишь как ты это делал год назад. Swiftpm или cocoapods избавляют от этого гемора.


Из не описанных минусов, это уменьшение холодной скорости запуска приложения. Где-то на 0.1 секунду за 1 framework (время зависит от многих факторов).
Когда начинаешь делить, модулей неожиданно становится слишком много, и проблема усиливается


Одно из решений это делать всё на статических либах, а не framework. Правда в этом случае придётся думать о ресурсах — и тут или Cocoapods в помощь или как в монолите — ресурсы оставить в одном месте.


P.S. Моё дело предупредить, а использовать это знание или нет решать не мне ;) вдруг проект на 10 модулей — одна секунда холодного запуска конечно много, но не критично.


P.P.S. Как показывает практика вначале лучше делить монолит разложив всё по обычными папкам, и только потом делать физическое деление.

Спасибо. На подобных сообщениях только и держится развитие библиотеки. Да, AutoFac на самом деле сыграл не мало важную роль в развитии — многий функционал взят из него и отсутствует у других библиотек под Swift.


P.S. если вы слушали доклад про устройство библиотеки, то возможно заинтересуют ещё одна статья: https://m.habr.com/ru/post/510174/

Спасибо. Алгоритм не выглядит сложным. Постараюсь его понять полностью — но надо с листочком бумаги посидеть.


А вот наличие реализации это хорошо — в ближайшее время сравню время поиска циклов, и эквивалентность результатов. После чего к статье допишу информацию об этом.

Проект рабочий. Я не в праве давать код, по которому строиться граф.


Но я сейчас занимаюсь визуализацией — сохраняю граф весь в dot формате. Это не полная информация, но этот файлик я могу дать, перед этим переименовав все названия вершин.
Если информации о наличии вершин, рёбрах, пакетах достаточно без конкретных данных то в течении сегодняшнего дня приложу отдельно к статье.


Для построения графа с целью поискать циклы этого должно быть достаточно.

Оно там даже больше чем экспонента растёт от количества вершин. Вопрос лишь сколько лишних операций надо сделать чтобы их найти. Одно дело 10к циклов и на них 100к операций, другое 10к циклов и на них как у меня было бы, в обычном обходе в глубину, 10^13 операций где-то.


Если рассматривать сложность не от количества вершин, а от количества циклов то идеально О(N). Боюсь правда такого нет, но возможно приближенно что-то подобное есть.

Спасибо. Почитаю. Теорию графов я помню только от универа где она была около месяца. Поэтому научные труды не искал — мне бы понадобилось много времени на поиск и почтение.


Скорей всего есть более оптимальные алгоритмы подходящие под мою задачу. Где-то читал, что можно через Остовное дерево находить.
Для моей задачи меня устроил достигнутый результат, который должен быть понятен большому кругу людей.


Я надеялся на комментарий от человека знакомого с этой темой — чтобы была возможность почитать как подобные задачи решаются на больших данных.


А циклы мне нужно найти все (не обязательно сохранять), чтобы проверить что они верные в рамках прикладной области. Для этого там есть различные проверки на данных которые хранятся в вершинах и рёбрах. И некоторые проверки требуют полную информацию — нельзя сказать по части цикла верный он или нет.


Я старался не вдаваться в подробности этих проверок, но возможно отдельной статьей напишу о всех проверках. Тем более мне кажется, что можно проверить ещё что-нибудь, а сообщество может предложить интересные идеи.

Хорошая статья. Да, я пожалуй с ней соглашусь во многом. Но я бы сказал так что for in ещё стоит использовать в алгоритмических задач — из-за аргумента, который написан в статье, возможность управления циклом continue break.


Ведь пока я писал алгоритм, тело цикла менялось раз 20 и там были варианты и с continue и с break.


В прочем forEach мне нравится использовать только в случаях когда он целиком означает некое законченное действие. Например, с removeFromSuperview() — тогда весь целиком forEach означает "удалить все subviews".
For in же сложнее воспринимать как единую операцию, но зато проще как Безымянную.

Дело вкуса. Я не люблю использовать forEach для подобных ситуаций. И чуть медленней работает нежели for in. Но разница настолько не значительная, что за аргумент не подходит.


P.S. У меня есть четкое деление когда for in а когда forEach, но это объяснить тянет на статью, чтобы понять почему я так делю.

Тем что он работает 95 минут. Это почти полный аналог 1-2 варианта алгоритма (там есть обе идеи).
Ну и он не совсем рабочий если почитать комментарии вначале был (там потом поправили).

Да так красивее, но where по моим измерениям годичной давности работает сильно медленнее. Поэтому я его не использую. Возможно мои данные устаревшие.

Information

Rating
Does not participate
Location
Новосибирск, Новосибирская обл., Россия
Date of birth
Registered
Activity