Pull to refresh

Comments 25

Программирование, программирование никогда не меняется.

Со времен книги
Эдвард Йордон "Путь камикадзе"

ничего не поменялось :-)

Если вы дочитали до конца и что-то для себя поняли, то спасибо вам.

Нет, это вам спасибо. Как был прав Ершов А.П., когда писал:


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

И анекдот хорош и к месту:


Кардиолог приезжает в автосервис, ему работяга машину чинит, потом говорит:
  • Слышь, мужик, вот я мотор перебираю — и ты мотор перебираешь, только человеческий — почему тебе платят на порядок больше?
    Кардиолог кивает, идёт к машине, включает зажигание и говорит работяге:
  • А попробуй при работающем движке теперь перебери!

Спасибо, Владимир Николаевич.

Прочитал ваши статьи "Пятьдесят лет на стезе программирования", и вам спасибо за них. Без понимания прошлого, будущее сложно построить.

Если все обозначенные стороны у такого человека развиты, то назовём его «золотой шестерёнкой», а цену за это назовём в конце статьи.

В статусе так называемые «золотые шестерёнки» находятся чуть выше мужиков ну и соответственно знают о разработке чуть больше. Также довольно-таки важный фактор состоит в том, что «золотые шестерёнки» имеют благосклонность авторитетов руководителей что даёт им не мало привилегий. Сами себя они никогда не назовут «золотыми шестерёнками» (так как это звучит довольно обидно) а называют они себя обычно «создающими движение бизнеса» или «ведущими».

Извините, не удеражлся.

Немного не так. Я эту тему во второй части раскрою. )

Отдельно скажу руководителям, что нужно опасаться работать с «золотыми шестерёнками»

Ну правильно, таланты нужно гнать в три шеи! Нам нужны верные и послушные (с).

А на самом деле нужно просто уметь работать. Те, кого называют "руководитель", часто этого делать не умеют.

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

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

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

  • Описал вычисления некорректно? Торопили, согласился сделать без тестов.

  • Не учёл негативный сценарий? Думаю только о позитивном, аналитика нет.

  • Не использовал сахар? Делаю как привык за последние пять лет.

  • Написал откровенно нерабочий код? Не знаю как написать рабочий.

  • Решение не полное? Тороплюсь к другу на день рождения.

К сожалению, наша жизнь — это компромисс между нашими желаниями и нашими возможностями.

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

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

В любом случае спасибо за статью, будет интересно почитать вторую часть. 

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

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

Извините, а как иначе этот рядовой разработчик научится битовым сдвигам? Магии с++ и прочему? Не говоря уж о том, что вообще-то битовые операции - это база

Я вот помню момент, когда появился .нет 3.0 и лямбды. Удобная штука, что и говорить, но часть коллег сразу заявила - не-не, не пиши так, мы не понимаем. Как так-то? Это инструмент, которым вы работаете; эрго, по всем стандартам, вы должны стараться использовать все его возможности. А если не знаете/не умеете - учитесь, епта

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

Мне иногда приходится писать код на С++, не коммерческий. Выполнение кода требует активной работы с оперативной памятью (численные методы, научные расчеты). Поэтому я предпочитаю никогда не использовать не то чтобы банальные smart pointers, но даже STL::vector, так как важно чувствовать эту самую оперативную память, операции выделения и освобождения памяти. Кроме того, оператор ветвления в ряде случаев я могу заменять арифметическими выражениями, чтобы избавить процессор от необходимости лишний раз ветвления предсказывать.

Это может показаться извращением, но зато мой код никогда по памяти не течёт (ведь я за этим слежу вручную), и работает быстро, что для меня важно. Справится ли с таким современный рядовой разработчик на С++, я не знаю. Скорее всего, нет. Другой вопрос, а оно ему вообще надо? ))

Бросайте этот C++, попробуйте Assembler. Вот где сможете почувствовать по полной вышеописанное.

Можно. Но мне нравится оптимизирующий компилятор С++, который позволяет мне не думать об архитектуре конкретного процессора, а работать в рамках лишь семейства, например x86. ))

>никогда по памяти не течёт (ведь я за этим слежу вручную

Мне кажется, что этот навык в проектах больше 100 строк может очень сильно замедлить разработку для большинства.

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

Оверхед всё-таки есть, и в какой-то момент начинаешь его чувствовать, есть неопределённость в реализации в некоторых местах STL, иногда может выстрелить. Кроме того, есть ещё STL::valarray, если уж использовать, то его.

На само деле, пример, конечно, экстремальный. Если бы это был коммерческий код над которым работает команда разработчиков, то пришлось бы смириться с некоторой неоптимальностью, откинуть все эти изыски и писать «нормально». И здесь я с вами был бы полностью согласен.

Поэтому я предпочитаю никогда не использовать не то чтобы банальные smart pointers, но даже STL::vector, так как важно чувствовать эту самую оперативную память, операции выделения и освобождения памяти.

Важно иметь возможность выстрелить себе в ногу?

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

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

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

А можете перечислить конкретные вещи, которым абстракции из стандартной библиотеки C++ мешают? И что, по вашему, входит в умение "работать с памятью"?


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

А почему вы так уверены в том, что не выстрелите себе в ногу?

Есть банальный тест на понимание происходящего (касается не только C++), это использование конструкции типа array.append(). То есть добавление нового элемента в конец массива с перевыделением памяти. Это дорогая операция за счёт необходимости выделить память под новый массив, перенести данные из старого места в новое, очистить память из под старого массива. Если такую конструкцию запустить в цикле на тысячи записей, то вместо продуктивной деятельности компьютер займётся постоянным перевыделением памяти.

Если мы говорим конкретно о STL, то классы там спроектированы весьма разумно. Но, например, есть операции типа vector::insert, которые требуют понимания того, что ты хочешь сделать. Конечно, кроме std::vector есть более подходящий для вычислительной математики std::valarray. Но есть нюанс в том, что стандарт не определяет реализацию.

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

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

Идём немного дальше. Например, у меня есть объёмная матрица в плотном формате, то есть некий двумерный массив, а обходить мне нужно её определенным способом. В кеш процессора она вся не влезет, так как может занимать гигабайты, значит процессор будет вынужден решать какой её кусочек нужно скопировать в кеш. То есть если это N массивов по N элементов, это одна ситуация, если это один массив из N*N элементов, то совершенно другая. Чтение из физической памяти меняется. Здесь уже могут начинаться проблемы с тем, что реализацию STL никто не регламентирует.

Возможно, мне самому будет удобно знать формат физического хранения данных. Например, я пользуюсь MPI и мне нужно передать кусок данных на другой узел. Одно дело, если я могу просто выхватить область физической памяти и послать её, другое дело, когда я должен заниматься упаковкой и распаковкой.

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

Конечно, я и на STL могу сделать то, что обычно делаю без него. Тут больше роль играет то, что он помогает людям забыть, что они работают с памятью. Иногда это вредно и лучше некоторые вещи в коде показывать в явном виде. Иногда, код не так интенсивно работает с памятью и можно писать с соблюдением «общепринятых подходов».

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

конструкции типа array.append(). То есть добавление нового элемента в конец массива с перевыделением памяти. Это дорогая операция
Если такую конструкцию запустить в цикле на тысячи записей, то вместо продуктивной деятельности компьютер займётся постоянным перевыделением памяти
Если речь о vector::push_back и подобных, то память выделяется с избытком и буфер растёт как степень двойки. То есть, реаллокаций будет logN от числа вставок. Кроме того, никто не мешает заранее вызвать vector::reserve(N), тогда вообще за весь цикл вставок будет ровно одна аллокация сразу нужного размера.
некий двумерный массив, а обходить мне нужно её определенным способом. В кеш процессора она вся не влезет, так как может занимать гигабайты, значит процессор будет вынужден решать какой её кусочек нужно скопировать в кеш
Неправдоподобно. Кеш-линия — 64 байта, т.е. всего лишь 8 double-ов/указателей/size_t. Вряд ли у ваших структур куски, обрабатываемые за раз, меньше 64 байт, чтобы было важно, как оно ляжет на кеш-линии.
Например, я пользуюсь MPI и мне нужно передать кусок данных на другой узел. Одно дело, если я могу просто выхватить область физической памяти и послать её, другое дело, когда я должен заниматься упаковкой и распаковкой
std::vector гарантирует последовательное размещение, берёте указатель на любой элемент, и дальше не важно — буфер получен через malloc или лежит в векторе.
либо использования одного и того же фрагмента памяти для хранения данных сильно разных структур
В C/C++ это чаще всего UB.

На прошлой работе приходилось работать с одним самописным фреймворком, созданным ровно двумя товарищами лет 15 назад. Код этого произведения имел довольно высокий уровень презентабельности (паттерны, интерфейсы, solid, вот это всё) и поэтому хорошо заходил менеджменту и новым разрабам на первых порах. Поэтому руководство решило "сэкономить" и все новые проекты ваять на его базе. Ну, а дальше понятно...

Вещи, изначально не заложенные в логику фреймворка, приходилось делать на палках и скотче. После примерно 80% завершения проектов выявились проблемы с многопоточностью и производительностью. С горем пополам решив их и отдав клиенту, через время оказалось, что решения не масштабируемы из за ограничений фреймворка. И т.д.

Через пару лет ушёл главный архитектор этого чуда, а чуть позже и другие товарищи, кто хоть как-то что-то знал. Пришли новые, а дальше как в статье.

Так что никакой кисы на проекте, пожалуйста. Иначе больно.

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

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

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

Мы иногда ведём проекты в крупных компаниях. Иногда в них архитекторы не только присутствуют номинально, а действительно работают. Люди исключительно полезные, они заранее для тебя снимают многие препятствия на пути. Грех таким не пользоваться.

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

Спасибо, интересная и полезная статья. Хоть буду знать, кто такой KISA.)

Sign up to leave a comment.

Articles