"Дефрагментация мозга. Софтостроение изнутри" - заметки на полях

| рубрика: Библиотечка | автор: SergeyBykov
Метки:

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

На протяжении книги Сергей несколько раз повторяет тезис Брукса «хороший программист, на порядок производительней среднего». Тезис многократно подтвержден и в моей практике. Но как и Брукс, Сергей обошёл анализ факторов, которые влияют на производительность программистов, и, как следствие, вопрос о том, как отличить хорошего программиста от среднего. Или, если посмотреть на проблему с другой стороны, как стать хорошим программистом? Для меня, как архитектора и руководителя проектов (РП), этот вопрос представляет большой интерес, т.к. не в последнюю очередь, результат проекта зависит от тех, кто будет реализовывать решения, описанные в тех. проекте. Программисты любят списывать все проблемы проекта на кривую постановку, но это только половина правды.

За мою карьеру я поработал с 4-5-ю по настоящему высококлассными программистами. Далее буду называть их Программист. Факторы, повышающие производительность программиста (под этим я подразумеваю не скорость написания строк кода, а скорость получения результата, готово для передачи в эксплуатацию):

  1. Глубокое знание используемых инструментов – языка, фрейворка, среды разработки. Знание не на уровне заученных приемов, преданных по наследству от предыдущих программистов, а такое, которое позволяет обосновывать выбор конкретных решений в рамках реализации поставленной задачи.
  2. Узкая специализация. Если Программист владеет навыками по .NET, он не возьмется за разработку сайта на Python. А если такая задача всё же будет поставлена, то Программист возьмёт достаточно времени на изучение нового инструмента (именно на изучение, а не на знакомство).
  3. Разработка полного алгоритма решения задачи на стадии изучения тех. задания. Состав процедур, классы, объекты БД, события и т.д. продумываются до того, как будет написана первая строчка. Программист, на своём уровне, проектирует реализацию и только после этого начинает писать программу.
  4. Самоконтроль. Программист сам, как минимум, проверяет как в полученной реализации, обрабатываются все исключительные ситуации, которые он предусмотрел на стадии проектирования реализации.
  5. Постоянное повышение квалификации и углубление знаний. Если Программист обнаруживает пробел в знаниях, то он не использует первое посланное Богом Гуглом решение, а изучает проблему и выбирает оптимальное обоснованное решение.

Как РП может понять, что он имеет дело с Программистом:

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

Я пришёл к выводу, что при тестировании кандидата, нужно давать не сложное, а «хитрое» задание. Задание, в котором заложено внутренние противоречие (придумать такое задание не просто, но если получиться, то на «эту блесну можно ТАКУЮ рыбу поймать»). Допустим контрольное время решения 1 час. Если чрез 10-15 минут, кандидат начинает задавать вопросы и намекать на ошибку в задании, стоит присмотреться к нему по внимательней. Если в конце контрольного времени, кандидат говорит, что почти всё работает, но надо отладить 2-3 особых случая, то это типичный средний программист. Думайте сами, решайте сами, кто вам нужен.

Большая часть книги посвящена ООП. У меня с изучением ООП не сложилось, мысли после знакомства с C++ у меня были как у девушки (Кошмар!!! У меня женская логика!), описанной в главе «Эволюция аппаратуры и скорость разработки» на стр. 42 – зачем всё это нужно?

Я не смог осилить ни Страуструпа (сломался где на 50-й странице), ни Буча (страница 20-я где-то). Те не менее я был воодушевлен и ожидал появления библиотек прикладных классов (документ, инвойс, накладная, склад и т.д.) из которых можно было бы конструировать приложения. А дождался классы – подключение к БД, список, квадрат, окно. Для меня ООП – обманутые надежды и разочарование. Одним из мотивов создания Ultima-Seller было желание восполнить этот пробел…

Долгое время я считал, что отсутствие в моём багаже теоретических знаний по ООП является ограничением. Но, оказывается, никакой теории нет. Спасибо Сергею, он снял с меня проклятие ООП.

Критические мысли про пример с книгой из главы «Думать головой» (это я люблю – думать). Не могу согласиться с подходом «Класс «Книга» для библиотеки, магазина и читателя – это три разные взгляда на одну и ту же сущность с отличающимися ассоциациями и обобщениями» (стр. 128). По сути это подразумевает свой класс «Книга» для каждого места учета – «Книга в библиотеке», «Книга в магазина», «Книга у читателя». Я придумал эти названия классов, но они мне не нравятся. Это «не наш метод».

С одной стороны Сергей критикует «птолемеевские системы» (субъективные системы, зависящие от точки зрения проектировщика), с другой стороны – оказывается книга в магазине, не то же самое, что книга в библиотеке. Далее на стр.130 он исправляется и помещает объекты одного класса «книга» в разные контейнеры. Чем может смутить читателя.

Книга, она, как говорится, «и в Африке книга». Этот класс обладает устойчивым набором атрибутов (Автор, Название, Издательство, Код, …) и свойств (Написать, Издать, Рецензировать, Цитировать, …). Обобщаться книги могут с другими печатными изданиями, но для этого нужны основания вытекающие из конкретной задачи. Магазин или Библиотека это контейнеры для классов «Товар» и «Единица хранения». А эти классы уже будут посложнее, потому что внутри должны содержать ссылку на объекты разных классов и предоставлять интерфейс к атрибутам и свойствам эти классов. Товарами могут быть – книга, открытка, журнал. Единицы хранения – книга, журнал, газета, грампластинка, микрофильм, рукопись.

Хорошая новость – если нужно спроектировать изолированную систему для библиотеки или магазина, такие сложности не нужны. И принципы обобщения в этом случае должны быть другими. Поэтому рассуждения выше имеют смысл только в контексте проектирования «глобальной» системы учета книг.

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

Вывод: стремление к чрезмерной «объективности» в ходе проектирования системы, может привести к неоправданному усложнению модели. Определите рамки применимости проектируемой системы и принимайте проектные решения с учетом этих ограничений.

Удивило заявление Сергея, что с версии SQL Server 2012 MS объявил ODBC основным (родным) API к СУБД. Ссылки на прессрелиз или документацию не дано. Не буду сейчас обсуждать, что последние время техническая политика MS напоминает флюгер. ODBC по определению не может выступать в роли «родного», т.к. реализует API на доступ к слою хранения данных, который не зависит от конкретной СУБД. Поэтому по стандарту ODBC поддерживает SQL в стандарте 1992 года. Расширения Transact-SQL через этот API не доступны.

В главе «Гибкость или наживулька» Сергей делает вывод, что какой методикой не пользуйся, сложность программы/проекта растет до тех пор пока не превысит способности программиста. Выше головы не прыгнешь? Но ведь очень хочется. 2 возможных способа:

  1. Спиральный – описан у Сергея. Нужно снизить качество проектирования и тем самым сократить время стадий анализа и проектирования. Возникающие при этом риски нужно компенсировать планированием нескольких итераций.
  2. «Декомпзиционный». На стадии эскизного проектирования система разбивается на компоненты, которые соответствуют уровню компетенции проектировщиков. При таком подходе, отдельные компоненты могут быть отданы для разработки сторонним поставщикам или куплены. Риски возникают при сборке решения из отдельных компонент, их можно минимизировать за счет создания службы интеграции. Цена, которую придется заплатить, усложнение архитектуры системы.

Про «программные фабрики». По-моему, эта часть книги задумывалась как финал-апофеоз. Сергей старательно нагнетал атмосферу, пытаясь ввергнуть читателя в депрессию. Что бы в финале указать путь к избавлению и дать надежду на лучшее. Но у меня просветления не случилось. И вот почему. На вход «программной фабрике» нужно дать модель, т.е. проект. И тут вспоминаешь все предыдущие главы:

  • с языками моделирования беда - стандартов нет. Самых языков, пригодных для описания модели в CASE системах тоже не много. В итоге у каждой «программной фабрики» своя нотация для описания модели.
  • сам процесс проектирования остается сплавом ремесла и искусства, в котором результат зависит от верховного шамана проектной команды.

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

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

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

Отдельное спасибо за главу про Ultima-Seller. Я практически проигнорировал тему на этапе подготовки книги. Причина видимо в том, что эмоционально это история «неудачного проекта». Прочитать в конце главы «история продолжается» было очень приятно.