Pull to refresh
19
0
Кирилл @ws233

Руководитель мобильной разработки

Send message

А самое прекрасное – что чек-лист теперь уже можно и пытаться автоматизировать, шаг за шагом. Автоматизация "с нуля" всего процесса была бы неподъемной задачей, просто потому, что процесс не был формализован и описан. Теперь он формализован, описан, закреплен "на бумаге" – чего бы не взяться за автоматизацию с уже созданным на 80% по пунктам планом? :)
Молодцы! Действительно полезная вещь!

Подскажите, пожалуйста, а зачем в iOS реализовывать свои запросы с помощью curl? В инструкции по КриптоПРО нет ничего про это. Такое ощущение, что библиотека КриптоПРО подменяет системный уровень, аналогично тому, как это устроено на Android.

И ни слова про обратные стороны сего забавного когнитивного искажения. А они в АйТи на каждом шагу. Проявляются примерно так: "Смотрите я тут гениальный роутинг для АйОС собрал! Вот вам инструкция на 145 листах, первые 48 листов описывают инструменты, которые вам нужно подготовить, чтобы этот роутинг у себя собрать. Все просто! И естественно, гениально!"

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

Ознакомился, спасибо. Полезно.

Подскажите, а подобного обзора для современной навигации на SUI случайно нет?

По теме статьи. У Apple в UIKit есть реализация шаблона "Команда": селекторы, таргеты, responder chain, first responder. Цель шаблона в том, чтобы доставлять команды (в том числе на навигацию) от источника до исполнителя, т.е.от условной кнопки для пользователя до условного контейнер-контроллера (например, UINavigationController), который уже и осуществит навигацию (в данном примере - push).

По сути, это системная реализация вашего Навигатора.

Ну, а коли он у вас все равно работает с UIKit, то не пробовали ли вы заменить Вашу реализацию Навигатора на системную через responder chain, first responder, таргеты и селекторы?

5 лет прошло. Интересно, как выглядит в итоге Ваша навигация. Хотим и уже попробовали навигацию через UIKit (Свифт у нас старенький по объективным в РФ событиям, использовать последние версии не можем), видим в ней потенциал, но не хотим реализовывать Навигатор, т.к.кажется, что в системе это уже все есть. Хочется скорректировать наше направление, во избежание...

Добрый день. Устранили? Или это все же оказалась "фича"?

Ну, т.е. OCP можно использовать:

  1. и в узком смысле (стабильность интерфейсов), чтобы не провоцировать лишнюю работу в разработке (изменение клиентов под изменившийся интерфейс)

  2. и в широком (стабильность собранных ранее артефактов), чтобы не провоцировать лишнюю работу по тестированию, дебагингу, документированию старого.

Еще раз спасибо за тонкий, но очень важный момент. Мы пока в более узком смысле OCP рассматривали, но потребность не провоцировать и лишнюю работу по тестированию у нас очень актуальна. Поглядим, как теперь мы могли бы изменить процессы, чтобы и в широком смысле OCP удовлетворять и сколько это будет стоить конкретно в наших условиях. Плюсанул Вам кармочку. Редко такие ценные комментарии на Хабре дают.

Или есть какая-то другая интерпретация OCP?

Попробовал загуглить, не удалось найти Вашу интерпретацию. Но в Википедии интерпретация другая, как раз на интерфейсы (я их назвал контрактами в сообщении выше). Ссылается википедия на первоисточник – на книгу Object-Oriented Software Construction и её автора Б.Мейера. К сожалению, оригинал не читал, но что-то мне подсказывает, что Википедия сильно не исказила смысл.

И почему вы говорите, что избегаете дублирования кода?

В принципе я уже ответил на этот вопрос. Сам код в единственном экземпляре. Есть лишь 2 интерфейса (2 контракта, 2 метода), которые этот код вызывают. Это чистое следование принципу сегрегации интерфейсов, который: а) самим эпплом активно используется (пруф). б) очень помогает принципу OCP, и в связке с ним дает вот такие существенные экономические эффекты.

с этими правками вы в любом случае нарушаете OCP.

Согласен. Если опереться на приведенное из Википедии определение, то по хорошему мы должны были оставить старый класс нетронутым полностью для старых клиентов и завести новый для новых. Новые клиенты должны были пользоваться новым классом.

Тут, видимо, мы машинально применили принципы рефакторинга К.Бека и объединили 2 класса, не нарушив интерфейсы и не спровоцировав ненужные изменения в клиентах. В итоге у нас не 2 класса (один из которых просто добавляет convinience initializer, реализуя тем самым новый интерфейс для удобства новых клиентов), а 1 - объединивший и старый и новый интерфейсы. Тут мы по сути тоже устранили дублирование машинально. Вы правы, стоит этот момент явно осветить в статье. Спасибо за эту тонкую деталь.

Давайте разбираться. Почему Вы считаете, что принцип нарушен?

Добавление нового свойства и инициализатора не меняет старый контракт – он закрыт для изменения. Но при этом мы в него добавили что-то новое, на что клиенты не обязаны завязываться – мы его расширили. Старых клиентов это не затронуло, новые могут пользоваться расширением. Мы выполнили оба условия принципа. Почему Вы считаете, что не выполнили?

Deprecated как раз поэтому и не используем. Это сломает старый контракт, мы запретим использовать старый метод (closed), которым пользовалась куча клиентов - это спровоцирует их на ненужные изменения и сильно удорожит разработку. Главная цель OCP как раз в том, чтобы минимизировать такие бесполезные изменения. Зачем обязывать клиентов использовать новый контракт, если их и старый устраивает и они получают необходимое им и без нового параметра? Таким образом, мы позволяем старым клиентам работать со старым контрактом, для новых (которым нужен новый параметр и расширенный функционал) мы завели новый. При этом во внутренней реализации наш старый метод будет просто вызывать новый, но с дефолтным значением вновь добавленного параметра. Этим мы избегаем дублирования и повышения стоимости поддержки нашего кода.

  1. Можно ли доработки для кастомизации пути снэпшотов предложить автору и сделать пул-реквест с ними в оригинальный репозиторий?

  2. Как и для чего используется версионирование скриншотов? Что происходит со старыми версиями? Какие могут быть сценарии использования?

Но ведь NSNotificationCenter – это ничто иное, как шаблон "Шина данных" ("Event Bus").

Разница в отсутствии типизации обусловлена лишь нюансами реализации. NSNotificationCenter реализован на языке без строгой типизации. Но это абсолютно не значит, что используя этот класс в Swift, Вы не можете получить строгую типизацию в шине данных.

Шаблон изучен на троечку. Применение строгой статической типизации к нестрого типизированным данным тоже. Пересдавать будете?ч

5 лет назад код на C++ без танцев с бубном собирался просто включением соответствующих файлов на C++ в ObjC-проект с изменением их расширения на .mm. Или даже и переименовывать не надо было, не помню уже -- старый стал. Полагаю, что и сейчас этот способ работает.

Этот же совет можно использовать и для работы со Swift ниже версии 5.9.

Ох, уж эти зуммеры, раз и навсегда похоронившие ObjC ^.^

И почему модульность нельзя реализовать исключительно на SPM?

... то надо хорошо подумать. Вьюмодель не должна ничего знать о вьюшках, в том числе и о том, как, какие и в каком порядке менять. Иначе получаете обратную зависимость и невозможность переносить вашу логику, например, на часы или телевизор. Или даже на макбук, Windows-компьютер или Android. Роутинг зависит от вьюшек, поэтому он платформенно зависим и должен быть инкапсулирован на уровне представления, а не опущен ниже.

Добрый день. У нас есть автоматическое формирование списка изменений, да. И даже автоматическое определение новой версии по анализу изменений в интерфейсе (Semver). Надеюсь, мы сможем обо всем этом рассказать в ближайшее время либо на Хабре, либо на Мобиусе.

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

Забавное следствие из OCP, о котором Вы не упомянули.

Если сохраняется стабильность протокола, то не повышается мажорная версия (расширение протокола повышает лишь минорную версию, определение Symver). Отсутствие изменения мажорной версии позволяет в многомодульных системах не менять зависимые модули. Таким образом мы добиваемся исполнения принципа инверсии зависимости за счет исполнения принципа OCP. Стоит нарушить принцип OCP в многомодульных системах (да и не только, просто в многомодульных это нагляднее, чем в связном монолите, но и в последнем эффект тот же) и вы теряете DIP и приобретаете зависимость верхних модулей от нижних. Что в свою очередь ведет к тому, что при изменении нижнего модуля вы вынуждены переписать полприложения.

Таким образом, следование OCP упрощает следование DIP. В статье вы указали на обратное утверждение: "Следование DIP упрощает следование LSP и OCP". Оно тоже верное. А отсюда следует, что начиная правильно использовать любой из этих принципов, вы, желая того или нет, вынуждены будете следовать всем трем. И на самом деле всем 5, ибо они все аналогично упрощают работу друг с другом. В итоге Вы получите синергию всех 5 методов, значительно ускоряющих вашу работу. Эти 5 методов взаимно не позволят вам нарушить ни один из них.

Такие забавные пирожки у тёти Клавы :)

За статью – респект. Примеры хорошие.

Поэтому не нужно защиты в общий доступ выкладывать. Одно дело про них прочитать человеческим языком, другое – сидеть и ковырять защищенный в несколько слоев бинарь.

Что будет с тестом, если функция loader.loadMovies() подвиснет?

1
23 ...

Information

Rating
7,832-nd
Location
Москва, Москва и Московская обл., Россия
Works in
Registered
Activity