Начну с того, что открою маленький секрет: выступление директоров Ульяновских компаний, описанное в первой части поста, было на самом деле не в начале лекции, а в середине, примерно после «вводной» её части. Вот с нее я, пожалуй, и начну.
На ней нам показывали реальный документ (Software Design Document – SDD) — описание структуры программы, который пишется программистами для программистов. Документ этот писался в Симбирсофте, на английском языке. Забавно: в нем, в графе «дата написания» стояло 2 числа – даты написания первой версии документа и второй. Юмор заключается в том, что по факту, первая версия документа писалась за полгода до второй, но стоявшие числа различались всего на один день! Вот так вот, оказывается, пишется реальная документация. :) Власенко заострил внимание, когда этот документ может быть полезен, и зачем его вообще пишут:
- Главное: это облегчает работу с программой на этапе сопровождения, потому что к моменту, когда надо будет что-то срочно исправить в программе, то люди, разрабатывавшие её, могут уже либо забыть о том, что они писали, либо вообще перейти в другую компанию.
- Второе, но не менее важное: наличие SDD облегчает «подключение» к проекту новых людей. Им становится проще разобраться в имеющихся исходниках, и они быстрее понимают, как и что работает.
После знакомства с этим документом, и после того, как подошли все опоздавшие, слово было передано директорам.
По окончании их выступления, мы перешли непосредственно к теме лекции – этапу «Реализации».
Сначала, был поднят вопрос стиля программирования. Было сказано, что стиль у программиста должен быть обязательно. Причем он должен уметь его изменять в зависимости от надобности и особенностей проекта. Наличие стиля – первое, на что проверяется код тестового задания. И, если его нет – то претендент на вакансию перестает быть таковым.
Было рассмотрено три возможных «адекватных» стиля программирования на языке С++:
-
1234567while(1){for(int i = 0; i < n; i++){a[i]=0;}}
-
12345while(1){for(int i = 0; i < n; i++){a[i]=0;}}
-
1234567while(1){for(int i = 0; i < n; i++){a[i]=0;}}
Было отмечено, что:
- Первый вариант, в данном случае, выглядит слишком громоздким. Однако, в некоторых случаях он может быть более читаемым;
- Второй стиль – компактный, также достаточно понятный. Но, иногда он может быть чуть менее удобочитаемым, чем первый.
- Про третий вариант стиля было сказано, что некоторым он нравится, но сам Власенко его никогда не использовал. И мое ИМХО: слишком уж тяжело придерживаться такого стиля: много «табуляций» придется ставить ручками.
После рассмотрения вопроса о стилях, перешли к Эффективности.
Я надеюсь, что большинство читателей представляют себе, чем отличаются O(1), O(n) и O(n!) при оценке сложности алгоритма программы. Если нет, то предлагаю почитать Википедию по этой теме.
Также, было сказано, что важное значение имеет время отклика интерфейса для юзера. Так, в одном из проектов Симбирсофта, оно не должно было превышать 2 секунд.
В завершение этой темы, нам порекомендовали почитать книжку Макконнелла С. «Совершенный код».
После чего перешли к обзору методов решения проблем с производительностью. Были выделены следующие способы:
- Замена старой техники на новую (например, поставить новейший суперкомпьютер, который вычисляет бесконечный цикл за 5 секунд :));
- Профилирование (поиск «узких» мест);
А вот уже с этими «узкими» местами делать можно следующее:
- Использовать оператор goto (как в стандартной реализации qsort). Следует напомнить, что goto надо применять с большой осторожностью и только в крайних случаях. И, желательно, только для быстрого выхода из цикла;
- Писать на ассемблере особо критичные по времени участки кода;
- Изменить алгоритм на более быстрый (одно из самых эффективных решений);
- Использовать кэширование;
- Использовать «ленивые» вычисления. Т.е. вычислять что-то непосредственно перед тем, как это понадобится. Яркий пример – индексация справки в продуктах Microsoft только во время первого её запуска;
- Предвычисления. Активно используются при написании игр. Суть в том, что, например, чтобы не вычислять синус каждый раз заново, в машину загоняется вся таблица Брадиса и, в дальнейшем, данные берутся из нее. Что получается в несколько раз быстрее.
- Разворот циклов. Т.е. запись вида
1234for(int i = 0; i < 4; i++){a[i]=0;}
Заменяется на
1234a[0]=0;a[1]=0;a[2]=0;a[3]=0;
В конце лекции было сказано несколько слов о самодокументированных программах, когда переменные имеют говорящие названия. И/или многое понятно из комментариев.
Закончилась же она «рекламной» речью Власенко об особенностях приема на работу в Симбирсофте, которые также были описаны в предыдущем посте.
Полезная статья? Их будет больше, если вы поддержите меня!