Обновить
23
Кирилл@ws233

Не гадьте в карму, лучше пишите, в чём не согласны

0,1
Рейтинг
14
Подписчики
Отправить сообщение

В копилку каверзных вопросов для собеседований. Добавьте в ваш граф ретейн цикла еще один объект, и 9 из 10 собеседуемых его уже не найдут.

И еще один. Какую из ссылок в графе ретейн цикла по теории можно сделать слабой для устранения проблемы? А какую нужно, чтобы не создать себе других проблем? Как определять ту единственную связь, которую в графе безопасно ослаблять?

Вот тут из 8 вхождений 7 -- это manual reference counting, и только одно - manual retain release. Правда, в этой же статье есть ссылка и сюда. И вот тут уже дается определение MRR, но тоже всего в нескольких упоминаниях. Имхо, не стоит так категорично. Кажется, что даже сами Apple вполне себе используют аббревиатуру MRC. Да и в русском сообществе она очень популярна. Ну, и так ли важно, как называется технология, или все же важнее понимают ли разработчики, как она работает?

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

Вот тут мы как раз и показываем вариант, как подружить Вашу идею с типами вьюмоделей с системным кодом. Вводится простая карта соответствий типа вьюмодельки (ваш Item) на идентификатор ячейки для реюза (та самая строка, которую по дефолту делают именем класса и сразу стреляют себе в ногу). Вам больше не надо дублировать системный код. Ваша реализация упростится и потеряет еще несколько счетчиков, от которых Вы так хотите избавиться. А также Вы не будете опускать вью слой аж до уровня парсера и нарушать тем самым принципы построения надежных приложений, типа SOLID или слоистой архитектуры.

Да, в цикле статей мы пока еще не описали, как аналогичный механизм применяется и для обработки действий пользователя. Но статья уже в процессе подготовки и скоро появится. А пока в качестве домашнего задания :) Вы вполне можете подумать, как применить данный подход и к обработке действий пользователя по ячейкам. Ваш код еще сильнее похудеет.

Мне казалось, что под константой с подразумевают все же количество повторений последовательных циклов, а не время выполнения одного прогона цикла.

Но даже если и смотреть на с под таким углом, как говорите Вы, то получим мы следующее. Константы с1 и с2 будут лишь определять точку пересечения графиков друг с другом. Как экспонента и логарифм. Всем понятно, что экспонента на больших значениях более медленный алгоритм, чем логарифм. Но на значениях до 1, у них прямо противоположный эффект.

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

Для упомянутых вами алгоритмов, кмк, эти значения не такие ужасные. Да и инвертирование картинки получится лишь на малых значениях н до точки пересечения графиков. А дальше мы все равно будем получать "теоретический" неперевернутый результат. А смысл искать оптимальный алгоритм на малых значениях n? Там вообще не важно, оптимален алгоритм или нет. Быстр он или нет. А вот как можно исковеркать алгоритм так, чтобы точка пересечения графиков ушла так далеко вправо, чтобы даже на больших значениях n упомянутая вами картина была верна, я даже думать не хочу. Это что-то из области такого страшного говнокода, что надеюсь, никогда я с этим не повстречаюсь.

И все же ближе к практике. Упомянутые Вами алгоритмы на n=1000 дают инвертированную картину? Вы проводили исследования? Можно где-то почитать?

Согласен, что сравнение двух целых чисел, которыми обычно характеризуют номера сборки, проще, чем парсинг строк в формате «1.2.17» и «1.5.13» и поочередное сравнение номеров мажора, минора и патча (на все это хорошо бы иметь тесты)

Почему-то мне казалось, что в строку iOS уже вшит этот функционал. Нет необходимости дублировать имеющийся функционал и писать на копию тесты.

Как же так? O(cn) - это просто с последовательных циклов, которые можно легко свести к одному циклу, приведя тем самым алгоритм O(cn) к O(n). Именно поэтому константу всегда и упускают в такой нотации. Так что любой самый медленный O(cn) всегда можно сделать быстрее, чем O(n^2). Или есть какие-то случаи, когда нельзя? Можно примеры таких случаев?

Вот и настало то время, когда можно писать статьи на Хабре и выступать на митингах о своем собственном процессном фреймворке, который решает все проблемы, имеющиеся в *Подставь сюда свой самый ненавистный процессный фреймворк*.

Одно время был бум архитектурных реализаций.

А теперь катится волна процессных фреймворков.

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

Но, это же будет противоречить и опыту и описанию Apple'а. Я четко вижу в своих приложениях, как память уменьшается, когда у меня еще есть unowned ссылки, но уже нет strong ссылок.

Это как-то можно объяснить?

Но погодите. У меня что-то не сходится.

HeapObject - это и есть выделенный нами объект, правильно? Вернее обязательная часть нашего объекта, содержащая isa и счетчик ссылок (ну или ссылку на side table). Верно? дальше за этой обязательной частью лежат хранимые переменные нашего объекта. И вот это все вместе - наш объект. Правильно?

Теперь, если у нас счетчик сильных ссылок стал равен 0, то мы можем освободить всю эту конструкцию из памяти, т.к.она нам не нужна. Но получается, что мы ее не можем освободить, т.к. нам нужна side table, по которой мы сможем сказать, что вот такой-то объект больше не существует. Т.е. получается, что объект живет в памяти не до тех пор, пока на него не осталось сильных ссылок, а он живет пока на него есть вообще хоть одна ссылка или хотя бы пока на него не осталось даже unowned ссылок? Ваша цитата: "А unowned счетчик отмеряет время жизни памяти, выделенной под объект." говорит об этом же?

Но погодите, тогда это полностью противоречит тому, что нам дает Apple. Точно ошибки в понимании логики нигде не произошло?

И второй вопрос. Какие прикладные задачи теперь можно решать с этим знанием в финтех-проекте? Вы же не просто ради спортивного интереса реверс-инжинирили компилятор? :)

Статья мощная. Но остались нераскрытые вопросы.

А зачем же нам счетчики weak и unowned ссылок? Со strong понятно -- это счетчик жизни объекта, по нему мы понимаем, жив объект или уже мертв. А зачем считать weak и особенно unowned. Допустим, что weak нужен просто для валидации, что мы нашли в памяти нужное число ссылок для их обнуления. Хотя зачем может быть нужна такая валидация? А вот про unowned вообще не могу предположить, зачем...

Есть у Вас ответы на эти вопросы?

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

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

Спасибо. Статья интересная. Ждем продолжения.

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

Тут еще такие мысли. Кажется, что при переходе не реактивное слежение за сигналами, читать явно значения переменных не стоит. Т.е. не стоит смешивать активное и реактивное программирование. Если уж у вас везде реакции на изменения, то убрав явное чтение значений в каждый конкретный момент, Вы исключаете саму возможность прочитать неверное состояние. А сигналы рано или поздно дойдут до всех подписчиков в актуальном состоянии.

Кажется, что единый Стейт все же не решает проблемы многопоточности, ну вот никак. Даже с единым стейтом вы все равно не застрахованы, что ваше приложение не окажется в конкретный момент времени в непредусмотренном состоянии. Даже с единым стейтом, система в любой момент времени может перекинуть вас на другой поток. Даже во время вашего перехода из одного стейта в другой, пока этот самый Стейт еще не обновился полностью. И вы получите тот же самый рассинхрон, которого Вы так опасаетесь. Проблему мог бы решить единственный поток, в котором и происходят все смены состояний и их чтения, но мы прекрасно знаем, что в iOS работать в одном единственном потоке практически невозможно. А значит, единый Стейт для Вас - это лишь попытка себя обмануть. Кажется, что единственный возможный выход из данной проблемы - это правильная работа в многопоточной среде с атомарными записями и чтениями состояния. И тут уже не важно, единый у вас Стейт или распределенный, но обеспечивающий атомарность записи и чтения. Тем более, что Вы тоже согласны, что Стейт в Redux не обязан быть единым. Кажется, что единый Стейт обеспечивал бы те плюсы, что Вам нужны, в каком-то другом программерском мире, но не в иосном. Возможно, я ошибаюсь.

Подскажите, а почему State единый и такой массивный? Чем это обусловлено? Кажется, что если просто поделить один божественный State на кучу мелких, но подписывающихся друг на друга, большая часть ваших проблем, если не все, уйдут. Тот же профиль вы выделяете в отдельную сущность, за которой потом следит тот, кому нужен профиль, без слежения за всем "богом". Кажется, что в Redux не должно быть ограничения на то, что состояние обязано быть одним. Но даже если и так, можно же завести под каждый UI-компонент свой фасад, который будет под собой объединять по нужной Вам логике отдельные независимые стейты. Кажется, что корень проблем модуляризации у Вас -- это попытка затянуть God-объект, связывающий в большой клубок все ваще приложение, в модульную архитектуру. Кажется, что так не выйдет. Модуляризация подразумевает в том числе разнесение модели и стейта на независимые куски.

В чем на Ваш взгляд заключается усложнение?

Портянкой нет. А вот пояснить выбор именно такого решения даже в атомарном коммите нужно. Иначе, появятся вопросы про оверхед или "я бы сделал вот так". А потом долгая переписка о том, почему же все-таки было выбрано именно такое решение. Вроде всем было бы проще, если бы даже атомарный коммит сразу ответил на вопрос "Почему?".

Спасибо. Снова хорошие мысли.

Вопрос контроля. Не смотрел на проблемы собственных реализаций с этой стороны. А ведь действительно. Многие могут реализовывать свои решения потому, что не понимают, как управлять тем, что есть у Apple. Что касается управления кешом через dataTask, так я, наверное, и не знаю-то, как это делается в деталях ^.^ Вы тоже натолкнули меня на хорошие мысли, спасибо за это.

Ну, и желаю Вам опубликовать статью по итогам исследований нативного кеширования. Материала должно набраться много и очень толкового.

Снова спасибо. Опять хороший ответ.

Итак, зафиксируемся:
1. dataTask умеет кешировать запросы из коробки
2. dataTask можно использовать для загрузки небольших изображений. Нигде явного лимита не указано. И лимит этот косвенно можно выявить из других признаков и рассуждений (хоть и не тех, что вы привели, по моему мнению, но об этом уже не будем).
вы с этим согласны.

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

Ок, давайте разбираться.

Мы же с Вами уже разобрались, что dataTask кешурет данные. Т.е.они все же складываются на диск. А раз они складываются на диск, то с диска же они и читаются в оперативную память. Так? Уверен, что так.

Давайте теперь разберемся, а как же они читаются? А читаются они стандартным для iOS способом, применимым повсюду. Через NSData. В этом можно убедиться в конкретном примере, посмотрев тип данных первого параметра замыкания, вызываемого в результате выполнения dataTask.

Что ж открываем документацию, читаем:

The size of the data is subject to a theoretical limit of about 8 exabytes (1 EB = 10¹⁸ bytes; in practice, the limit should not be a factor).

Переведу и поясню. Теоретически, размер буфера в NSData ограничен 10ю в 18й степени (безумное число), а практически, вы не должны заботиться об этом лимите. Все работает для вас с такими объемами.

Как Вы думаете, как Apple удалось такого достичь на мобильных телефонах с гораздо-гораздо меньшим объемом оперативной памяти?

Все верно! Буфер NSData хранится на диске, а не в оперативной памяти. Это очень легко проверить, открыв какой-нить фильмец на пару гигабайт размером через NSData.

Таким образом, первое предложение, за которое вы зацепились, значит не что иное, как то, что данные вам возвращаются в виде объекта NSData, с которым вы можете работать, как-будто они находятся в оперативной памяти. Вам просто не нужно это делать самостоятельно, как если бы вы работали с downloadTask.

Что же касается замечания о том, что надо конструировать UIImage. Так он (как и Image в Свифт) работает поверх NSData все с тем же механизмом. Я это четко осознал, когда бил на тайлы 100МБ jpeg военную карту Москвы на 4S. Просто прикиньте, какой размер эта карта занимает попиксельно после декодирования jpeg. И тем не менее данная карта прекрасно отображалась на экранчике мобильного телефона. Правда, плохо масштабировалась, что я позже и решал тайлингом.

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

Есть еще аргументы для меня и сообщества в пользу ручного кеширования и повторения работы Apple самостоятельно вместо того, чтобы взять коробочное решение?

Информация

В рейтинге
4 054-й
Откуда
Москва, Москва и Московская обл., Россия
Работает в
Зарегистрирован
Активность

Специализация

Разработчик мобильных приложений, Программный менеджер
Ведущий