?

Log in

No account? Create an account

Предыдущий пост поделиться Следующий пост
Логика неизбежности
lex_kravetski

Шаг первый



Я — профессионал, мастер своего дела и вообще. Пока эти не умеющие проектировать долбодятлы пытаются как-то выкрутиться, я солидно и по-взрослому выстраиваю архитектуру проекта так, чтобы никаких ошибок с управлением памятью не возникало. Мне, с моим развитым интеллектом и широким кругозором, не тяжело сначала подумать, а потом сделать, поэтому связки new-delete вполне достаточно. Я ж не быдлокодер какой.

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

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

Вот что значит знание языка: пока эти дебилы выворачивались, я, с моими знаниями, сразу сообразил, как сделать необходимое. Это потому что интеллект и руки прямые!


Шаг второй



Чего я тут подумал-то. Вот есть у меня класс. В его конструкторе создаётся десяток объектов. А потом они удаляются в деструкторе. Если я эти объекты оберну в мой DeleteOnExit, то ведь они тогда сами будут вместе с родительским объектом удаляться. А что, удобно. Вот что значит системный подход! Нашёл решение и сразу же его применил. Называется «повторное использование». Поняли, ламерьё, как надо-то? Это вам не быдлокодить, это — торжество разума.


Шаг третий



Позвонил один знакомый и сказал, что им срочно нужен ещё один программист. Предложил на полставки после института у них подрабатывать. Ну так а то! Знают, где профессионалов искать!

Согласился. Вышел на работу и сразу охренел. Нет, я, конечно, подозревал, что Фотошоп какой имеет более длинный код, чем моя утилита, отслеживающая изменения в директории, но что б настолько! Да такого размера код за всю жизнь не просмотреть, зараза. Это ж надо так много написать! Я ж теперь уже наверно не смогу каждый день все строки кода перепроверять. А у них тут в архитектуре, со слов главного программиста, бардак полный: здесь создали объект, туда на него указатель передали, а оттуда он ещё вон туда ушёл. По ходу, архитектурой эти лохи вообще не владеют.

Поговорил с коллегой. Тот сказал, что в моей утилите по коду один проход делается, а потом приложение закрывается, так что я вообще мог бы не заморачиваться с delete-ом — один хрен, на выходе вся память освободится. Странный, блин: если delete не вызвать, то утечки ж памяти будут.

Сделал функцию и вписал в неё мой DeleteOnExit. Ничего так. Подход рулит. Но во второй функции оказалось, что указатель на объект надо наружу передать. Хотел ведь поначалу отрисовку прямо у себя сделать, но главный программист сказал, что так нельзя, что у них для отрисовки целая иерархия объектов используется, и я должен в неё как-то свой объект передать. На хрена, интересно, им такая иерархия? Чего бы сразу на месте не нарисовать-то? Но спорить не стал. Не люблю конфликты

В общем, объект должен уйти в их иерархию. А где его тогда удалять прикажете?

Проанализировал задачу, снова поразился, как много у них всего написано. Понял, что DeleteOnExit тут не прокатит. Придумал: этот объект мы положим в хранилище объектов, которое я сделаю, а там каждый объект будет обёрнут в DeleteOnExit. При удалении хранилища, удалятся и все объекты в нём. А в функции объект будем класть в хранилище. Вот что значит — системный подход. Это вам не быдлокодить.


Шаг четвёртый



Так всё хорошо шло и всё испортили. Я было наловчился складывать все объекты в хранилище, но неожиданно оказалось, что некоторые объекты могут удаляться и раньше. Их, оказывается, можно через специальный диалог этого типа Фотошопа стереть навсегда. Переделал хранилище, чтобы можно было и до его удаления некоторые объекты удалять, но delete теперь в двух местах. Иногда в одном их них возникает null pointer exception. Почему — неясно. Сложная у них всё-таки архитектура. У меня проще была. Я ж всё-таки не быдлокодер. Я — настоящий мастер своего дела.

В общем, придумал: пусть будет специальный объект, в котором другие объекты создаются и удаляются. delete в этом случае написан только в одном месте и мы всегда там можем запомнить ещё не удалённые объекты. Поэтому delete вызовем ровно один раз. А для уже удалённых delete просто будем пропускать. Всё проще, чем разбираться со всеми возможными последовательностями вызовов. Эх, всё-таки я — молодец. Другой бы не додумался.


Шаг пятый



Коллега сказал, что сделанное мной называется «фабрика». Неужели такое кто-то уже придумал? Странно. Ну да ладно, пусть, я не гордый. В общем, с фабрикой стало гораздо проще. Но и тут вдруг встретилось неразрешимое противоречие — теперь иногда delete не вызывается вообще. Ну, оказалось, что есть ещё несколько мест, куда мои объекты надо передавать, поэтому удалять объект просто по запросу из диалога-удалятора нельзя, надо дождаться, когда его и из других мест тоже удалят.

Поразмыслил и всё понял. DeleteOnExit пусть на всякий случай вызывает удаление через фабрику, но сам при этом считает, в скольких местах про этот объект всё ещё помнят. Когда про него помнить перестанут, вот тогда-то всё и удалится. При удалении моего хранилища, правда, всё удалялось раньше времени, а я так и не нашёл правильное место, куда удаление хранилища вставить. Слишком сложная у них всё-таки архитектура. Не то, что у меня. В общем, от хранилища пришлось отказаться. Всё, значит, хранить в DeleteOnExit — он ведь всей полнотой информации теперь обладает.

Тяжело только разрулить одну ситуёвину: я, прежде чем передать указатель куда-то, у DeleteOnExit вызываю у него increment, чтобы, значит, количество мест, где объект знают, увеличить, а вот когда у него decrement вызвать — неясно. Самое плохое, из некоторых мест мой указатель уже безо всяких инкрементов дальше передаётся. То есть, я не все места помню, где мой указатель есть. Повписывал decrement где надо в коде, но хрен знает, все ли это места? Да и выглядит длинновато: кругом проверки, мой ли это указатель. Надо бы договориться, чтобы все DeleteOnExit повсюду передавали, а то неудобно. Отличная ж идея.

Только надо бы этот объект переименовать. А то он теперь совсем не DeleteOnExit. Надо чего-то типа «считающийся указатель» сделать. IncDecPointer, как-то так.


Шаг шестой.



Пообщался на форуме с каким-то чуваком. Он мне сказал, что такой поинтер уже давно придумали и реализовал я его не совсем правильно — не учёл ряд нюансов. Дал посмотреть, как надо. Оказалось, нужный объект уже даже в библиотеке есть. Кругом меня опередили. Не понимаю, одни ж быдлокодеры повсюду, а что я ни придумаю, оно есть уже. Даром что ли столько времени язык изучал? Думал, вообще всё знаю. Даже про сборщики мусора из-за которых всё тормозит. А вон оно как. Ну да ладно, я не гордый, пусть уже придумали — не могу же всё я один придумывать-то. Столько нюнасов — жизни не хватит. Моё дело — общая концепция. А детали пусть былокодеры делают.

В общем, заменил свой DeleteOnExit на библиотечный. Посмотрел код, а там такой уже используется. Но не везде почему-то. Спросил главного программиста. Тот говорит: не везде, поскольку не все про такой знали, а переделать ими написанное времени не хватает. Ну и следить за каждым он тоже не может.

Блин, ну надо же как-то было подумать перед проектом, архитектуру разработать. Не знали они, блин! Надо ж узнать сначала, а не сразу кидаться быдлокодить! Я, вот, всегда заранее продумываю архитектуру и прочие детали. Потому что я — профессионал.

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

Код огромен. Если я сейчас возьмусь менять везде указатели на смартпоинтеры, у меня наверно года два уйдёт. Поменял только в тех местах, где с моим кодом взаимодействие идёт, да и то не везде, поскольку в некоторых случаях было неясно, как менять. Мысленно проклял главного программиста: если чувак знал, что смартпоинтеры не везде, чего, нельзя исправить было что ли? Я теперь, как дурак, должен два года потратить на переделку? Да ну нафиг!

Итить! Кабы с самого начала всё на смартпоинтерах делали — проблем бы не было.


Шаг седьмой



Опять всё стало накрываться медным тазом. Нашёл случай, когда смартпоинтер тоже не срабатывает. Есть у меня, значит, одно хранилище, которое внутри себя содержит несколько объектов. Но эти объекты знают, в каком хранилище они хранятся. У них смартпоинтеры на хранилище, а у хранилища — на них. В результате ни хранилище, ни объекты не удаляются. Хорошо вовремя заметил — эти хранилищи у меня создаются в промышленных масштабах для промежуточных операций. Я-то надеялся, что они удаляться будут сами, но нет, не удаляются.

Матерясь сделал функцию принудительной очистки хранилища и вставил её везде, где оно используется. На следующий день пришёл коллега и сказал, что память у нас течёт и это похоже из-за моего кода, хотя он не уверен. Стали смотреть. Оказалось, что кто-то моё хранилище уже стал использовать. Только он не знал, что оно не удаляется. Вот ламерьё-то! Вставили в его коде очистку хранилища. Поражают меня такие люди: ни хрена ж не понимают, а лезут в программисты. Хотел ему в код обидные комментарии написать, но потом передумал — не люблю я конфликты.

Много думал. Вроде бы началось с того, что я не хотел писать delete. Нашёл отличный способ. Даже несколько отличных способов. Но теперь вынужден вместо delete вызывать очистку хранилища. Как-то не очень здорово получилось. Есть в этом какой-то подвох. Тем более, уже появились места, в которых ровно как с былым delete-ом неясно, в какой момент вызывать очистку. Подумал, что наверно нужна некоторая фабрика, которая будет запоминать все неудалённые хранилища и вызывать delete только в тех случаях, когда хранилище ещё не удалено. Но внутренний голос подсказал, что с этим будут какие-то проблемы.

Посоветовался со знакомым. Тот предложил завести глобальный объект, в котором все смартпоинтеры будут себя регистрировать. А тот будет как-то проверять, не только остались ли ссылки на этот объект, но ещё и нет ли ситуации как с хранилищем. Если есть, то в смартпоинтерах счётчик ссылок обнулять. Решению очень обрадовался. Я всегда говорил: главное — системный подход. Именно его не хватает быдлокодерам.

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

Несколько дней рисовал схемы на бумажке — ни фига непонятно. Идиотская какая-то идея, похоже. Вообще не решаемая. Даже я не смог решить.

Позвонил знакомому и сообщил, что он — идиот. Тот повесил трубку. Как есть — идиот. Зашёл на форум и там спросил. Мне какой-то козёл написал, что я — ламер. Целый день с ним ругался, пока меня там админ не забанил. По ходу, у них там целый питомник ламерья. Зашёл на другой форум, где меня знают как профессионала и никто не сможет сказать, что я ламер. Спросил там. Ответа не получил. Ну а собственно, чего я ждал-то? Я ж знаю, что там одни дилетанты собираются. Я ж сам им неоднократно писал, какие они все лохи. Такие вопросы задают, что читать смешно. Знания по нулям вообще.

Обратился к главному программисту с вопросом. Тот хмыкнул и посоветовал хранить в смартпоинтере ссылку на родительский смартпоинтер. Я не понял, как это поможет, и переспросил. Он сказал зайти через полчаса, а когда я зашёл, дал мне готовый класс. Надо же — соображает. А я-то думал, он такой же ламер, как и все вокруг. Правда, если он не ламер, то зачем нанял столько непрофессионалов? Ну да ладно. С моей помощью, надеюсь, всё наладится.

В данном мне объекте содержались комментарии по его использованию. Хм. А это даже удобно — с комментариями. Раньше я считал, что они — для лохов. Что по коду настоящий профессионал и так всё поймёт, но у главного тут получилось как-то непонятно. Я только по комментариям понял, как вообще этим всем пользоваться. То есть, когда программист неразборчиво пишет, комментарии всё-таки полезны. Я, конечно, пишу разборчиво, но ведь действительно, от других такого ожидать нельзя.


Шаг восьмой



Просмотрел класс главного программиста до конца. В конце была обидная приписка, что такие штуки вообще-то надо запускать в отдельном Thread, однако лично он сомневается, что я такое осилю. Он меня совсем за дурака держит? Думает, я не знаю, как использовать Thread?

Полез в интернет читать, как его использовать. Идиотская концепция — вообще ничего непонятно. И кто только такое придумал? Ощущение, все программисты на архитектуру болт кладут.

Читал три дня. Попробовал переписать код главного программиста с Thread-ом — программа через минуту виснет. С чего — неясно. Когда не виснет, объекты исчезают сами собой. Иногда появляется по две штуки сразу. Полный бардак. Подозреваю, этот Thread настолько криво написан, что постоянно бьёт чужую память. Ламерьё кругом.

Позвонил знакомому и извинился, что нагрубил в прошлый раз. Спросил, не знает ли он, где найти Thread без багов. Тот в ответ спросил, зачем мне. Я в общих чертах обрисовал свою задумку. Знакомый сказал, что объяснять долго, поэтому он мне сейчас пришлёт ссылку. По ссылке был уже готовый код того, что я придумал. Я очень удивился: и тут обскакали. Ну надо же. Ламер на ламере, а гляди ж ты! Наверно массой берут.

Скопипастил код себе. Заменил название. Эта штука зачем-то называлась GarbageCollector. Как будто они не знают, что Garbage Collector — это тот адский отстой, из-за которого ублюдочная Java тормозит. Я эту штуку назвал SmartPointerManager. Чтобы не порождать ненужных ассоциаций с быдлокодерством.


Шаг девятый



С этой штукой всё стало заметно подтормаживать. Полез на тот сайт, откуда я её взял, чтобы сообщить им, что они — ламеры криворукие и вообще прогать не умеют, однако наткнулся на приписку, которую в прошлый раз не заметил. Оказалось, это у них — пример. Который они дали для общего раскрытия общего подхода. А на самом деле ко всему этому надо ещё до фига всякого приписать: какие-то там сегментации, отслеживание времени жизни, мониторинг нагрузки, ещё чего-то. Тогда тормозить, говорят, не будет. Такая переусложнённая концепция — я в шоке. На сайте утверждают даже, что такое лучше прямо на уровне языка делать. С этой идеей согласен: SmartPointerC++ неплохо было бы заиметь.

Ещё говорят, указатели вообще тогда лучше не использовать, — ну а то я не знаю! Не даром же я начал везде смартпоинтеры писать.

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

Рассказал ему про идею SmartPointerC++. Он не ответил, но как-то нехорошо на меня посмотрел. Очень обидно как-то. Хотел ему нагрубить, но не стал. Не люблю конфликты.


Пока читал первый абзац и не врубился что это шутка - хотел с умным видом посоветовать умные указатели из STL. В последнем абзаце ожидал увидеть как ГГ перешел на Java.

нет! все же знают что жава отстой!

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

Драматично!
Вот ужо буст стандартизируют, будут, наконец, стандартные смартпойнтеры в C++ и прочие вкусняшки. Хотя и сейчас ничто не мешает. В Qt тоже с этим всё распрекрасно.
А без GC и правда жить можно, ситуёвина когда взаимные пойнтеры она редкая (я вообще не встречался с ней вживую ни разу). Можно использовать в одну сторону слабые или гуардед пойнтеры, в другую смарты.

Целиком Boost не стандартизуют, это, скорее, механизм откатки новых фич стандартной библиотеки и сборник идей для языковых концепций.

Художественное качество произведения всегда страдает, если художник небеспристрастен :)

Re: Ответ на вашу запись...

Каждый не беспристрастный читатель видит в тексте что-то своё.

Дидактически полезный текст!

Если отбросить всякие рефлексии мега-программиста :), то получится отличный материал для обучения ООП методом от проблем, идя от простой ситуации к сложной.

Как раз показано наростание аспектов сложной проблемы (освобождение памяти), необходимость пересмотреть ранее разработанное решение и, наконец, освоить ООП на том уровне, на котором проблему можно решить.

Но есть еще один момент - постоянное разочарование ГГ что "всё уже написано".

Как думаешь, Лекс, где граница между "изобретением велосипеда" и "копипастом" в жизни хорошего программиста? Как учить - не бояться изобретать велосипед или уметь находить код и копипастить его?

Понятно, что эти два умения друг друга не исключают, а дополняют, но речь идет об обучении, когда время ограничено и развивается какой-то один "скилл".

Re: Дидактически полезный текст!

В тексте никаких оценок нет, кроме как — личных оценок главного героя. Авторские оценки отсутствуют.

Вы разве программист?! =) Литературно - не тянет, да и от реализма весьма далеко.

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

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

Может быть, это персонально у вас подобное выглядело иначе, чем у всех?

Да, сборщик мусора - большое достоинство Питона :)

Re: Ответ на вашу запись...

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

(Удалённый комментарий)
(Удалённый комментарий)
>кто бы ни начал с DeleteOnExit, рано или поздно придёт к сборщику мусора
я так понимаю ради этого все написано было?

интересно к чему по логике неизбежности приходит каждый узнав про RAII...

ну или проще - к чему по логике неизбежности приходит каждый кто начнет с
"Чего я тут подумал-то. Вот есть у меня класс. В его конструкторе открывается несколько соединений с сервером. А потом они закрываются в деструкторе. БлаБлабла CloseOnExit..."

Re: Ответ на вашу запись...

> БлаБлабла CloseOnExit..."

А такой рано или поздно придёт к языкам с удобными механизмами создания DSL. Ну или как минимум с замыканиями.

Читаю вот я Лекса, читаю, и все думаю.
Надо как нибудь попробовать включить "-​fobjc-​gc-​only". Посмотреть к чему приведет.

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

Re: Шаг десятый

Количество шагов в перспективе ограничено только продолжительностью человеческой жизни.

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

Лекс не предлагал писать ПО для самолетов на Java :)

(Удалённый комментарий)
(Удалённый комментарий)
(Удалённый комментарий)
Правильный текст. За что и люблю программирование - можно постоянно находить новые велосипеды и строить их с нуля наслаждаясь процессом :)

Проясните дилетанту, а в каких случаях ГГ не избавляет от проблем с утечкой памяти?



Основная проблема - дефрагментация памяти. Есть медоты, которые решают эту проблему, но за счет ещё большей памяти.

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

интересно, что бы думал чувак, столкнувшись с коллектором, если бы начал не с DeleteOnExit, а прямо с него.

Re: Ответ на вашу запись...

Думал бы: заставили, сволочи, быдлокодить. :)

На самом деле реакции крайне разные бывают. Большинство вообще ничего особенного не замечает, поскольку ничего другого и не видела. Однако увидев прямое управление памятью позже — уже сильно удивляется и расстраивается.