Естественный подход к разработке сложных программных систем и объектно-ориентированные технологии.

    Введение

Речь пойдет о разработке программных систем (ПС) и объектно-ориентированных (ОО) технологиях. Эта статья - часть моего взгляда на разработку сложных программных систем. Я оставил за рамками данной статьи то, что предшествует разработке (например, определение целей). Это все очень важно, но у меня есть определенная специализация и я пишу про то, что хорошо знаю и чем сам занимаюсь. Кроме того, это статья, а не книга и я не могу здесь описать все, что знаю о разработке программных систем.

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

    Проблемы разработки сложных систем

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

    Важность уменьшения сложности

Обычно разработка программной системы оказывается настолько сложной, что любых имеющихся ресурсов (знаний, количества программистов, времени и т.п.) катастрофически не хватает. Причем далеко не всегда их можно просто увеличить (экстенсивный метод). Например, если вы наберете дополнительных разработчиков чтобы ускорить разработку, вы можете получить прямо противоположный результат. Ведь команда разработчиков - это сложная система и ее нельзя улучшить простым добавлением элементов. Схожая картина и со временем если процесс разработки плохо организован; увеличение времени на разработку может ничего не дать, кроме потери времени. В результате, разработчикам приходится мобилизовывать все свои ресурсы и работать на пределе своих возможностей. Я думаю, эти проблемы испытывают даже такие гиганты, как Microsoft, Borland, Symantec и т.п. Иначе чем объяснить такое низкое качество современного программного обеспечения?

Именно проблема сложности, на мой взгляд, и есть главная причина "кризиса программирования". А точнее, не сама сложность (мир вообще сложен, не только программные системы), а практически полное ее игнорирование. Разработчики операционных систем, прикладных пакетов, средств разработки, не моргнув глазом делают мир программного обеспечения все сложнее и сложнее, причем большая часть привносимой ими сложности ничем не оправдана. Все это можно было сделать ничуть не хуже (а то и лучше), но проще. Недавно я нашел в Интернете такой лозунг "Small is Beautiful" (простое прекрасно), вы думаете это имело отношение к какому-нибудь популярному продукту типа Microsoft Office? Нет, это был документ "Философия Unix" (http://hebb.cis.uoguelph.ca/~dave/27320/new/unixphil.html). По-моему, только там (unix, GNU, OSF - фонд бесплатных программ) это еще кого-то интересует.

Это все напрямую касается темы нашего разговора, потому что разработчикам системы придется пользоваться всем этим (плохими компиляторами, БД и т.п.). Кроме того, разработчики системы сами могут совершить аналогичную ошибку и усложнить себе жизнь.

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

    Объективная и искусственная сложность

Итак, рассмотрим повнимательнее то, с чем нам предстоит бороться. Сложность можно разделить на две категории: Проблема уменьшения объективной сложности относится скорее не к проектированию и программированию системы, а к определению целей разработки. Это все очень важно, но выходит за рамки данной статьи. Однако, в если кратко, то уменьшить объективную сложность можно, выбрав наиболее важные цели и отбросив менее важные (кстати, позже вполне может выясниться, что они вообще не нужны).

Искусственная сложность наоборот, в основном на совести тех, кто проектирует и программирует систему.

Для определенности введем еще один термин.

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

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

Итак, мы сосредоточимся на уменьшении искусственной сложности, а точнее, той ее части, на которую мы можем повлиять.

Искусственную сложность можно также разделить на две категории:

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

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

    Сложность и надежность

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

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

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

    Естественный подход

Естественный подход - это значит поставить перед собой цель - построить систему наиболее естественно (красиво, логично), используя наиболее адекватные средства. А не просто взять то, что валяется под рукой и сделать программу, которая: "а..., главное работает!"

Это придумали давно и, в более известном варианте это звучит так: "некрасивая машина не работает". К сожалению, этот принцип не часто соблюдается, а в программировании в последнее время вообще почти игнорируется.

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

    Неестественные средства

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

Например, Sql задумывался с целью уменьшить сложность работы с БД (вплоть до того, чтобы это могли делать простые пользователи). В результате, эти прогнозы в какой-то степени оправдались только на игрушечных примерах из нескольких простых таблиц, а во всех остальных (реальных и нужных) случаях сложность напротив возросла. Сейчас разработчики использующие Sql имеют много проблем, вызванных исключительно им самим. Например, оптимизация запросов или отображение реальной задачи в искусственную среду из кучи таблиц.

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

    Естественные средства

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

    Система как модель.

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

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

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

В процессе отображения из одной модели в другую происходит трансформация понятий исходной в понятия результирующей модели. Например, понятие "пользователь системы" может трансформироваться в объект типа User в программе, написанной на C++, а может - в строчку реляционной таблицы. Иерархия прав пользователя может трансформироваться в иерархию объектов типа UserPermission, а может, опять же, в реляционные таблицы. Но реляционные БД не позволяют легко естественно моделировать иерархию. Попробуйте, например, сравнить реализацию двоичного дерева средствами обычного языка и средствами SQL. Да, напишите обход этого дерева. После такой попытки, я думаю, вам станет ясно, что отображение иерархии в реляционные таблицы искажает исходные понятия и, в результате, мы получаем испорченный телефон. Происходит отрыв программы (модели нижнего уровня) от проекта и задачи (моделей более высокого уровня). Это неизбежно ведет к росту сложности и разработки, и сопровождения. Что и требовалось доказать.

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

Система будет тем лучше, чем ближе модель к тому, что она моделирует. Это означает, что модель должна оперировать с понятиями, близкими к задаче (предметной области).

Естественные средства позволяют строить модели более адекватные и естественные.

    ОО технологии - средство для уменьшения искусственной сложности

Для ОО технологии можно дать много определений. Можно, например, такое: ОО технология - это способ моделировать мир в терминах объектов и взаимосвязей между ними. Объект - более широкое понятие, чем, например, таблица, структура в C++, запись в Pascal-е, файл и т.п. Под объектом можно понимать целую фирму или одного человека, работающего в ней (вложенный объект). ОО технология включает в себя мощные средства, позволяющие оперировать понятиями объектов и их взаимосвязей.

Под это непросто подвести математическую теорию (в отличие, скажем, от реляционной технологии), эта технология сложна как и сам мир. Но она позволяет его естественно моделировать. Она позволяет рассматривать очень сложные системы как системы, состоящие из взаимосвязанных объектов, позволяет при необходимости абстрагироваться от их внутреннего устройства (инкапсуляция). Все участвующие в разработке (аналитики, программисты, проектировщики) получают возможность работать в терминах объектов. Исчезает разрыв между проектированием в терминах предметной области и, скажем, проектирования БД в терминах реляционных таблиц (объектно-ориентированную БД также можно проектировать в терминах объектов).

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

Все это позволяет снизить сложность разработки (точнее искусственную сложность).

    Реклама, мифы, мода и реальное положение дел.

Последние несколько лет мода на OO технологии. Но это тоже плохо. Ведь OO технология это - не самоцель, а просто средство, позволяющие снизить сложность разработки программных систем.

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

Объектно-ориентированное программирование (OOP) далеко не вся ОО технология, анализ и проектирование системы тоже должны быть объектно-ориентированными (OOA и OOD). В общем, необходимо перестроить все свое мышление, изменить всю философию разработки программных систем.

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

На это вполне может уйти несколько лет.

    Что делать?

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

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

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

То же самое относиться и к книгам. Если вы хотите почитать про объектно-ориентированное программирование, проектирование и анализ, то вы можете доверять книгам Б.Стауструп-а (автора языка C++) и Г.Бутч-а (книга по OO технологии).

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

    Приложение. Краткий обзор распространенных ОО языков программирования

Из языков, имеющих широкое распространение и подходящих для программирования сложных программных систем, OO технологию на мой взгляд, по- настоящему поддерживают C++, Smalltalk, TurboPascal (он же delphi).

C++

C++ являет собой компромисс между чистой ОО технологией и традиционными подходами (включая совместимость с языком "C") . Он также позволяет создавать быстро работающие программы (в этом он, практически, не хуже обычного "C"). Из всех перечисленных языков C++ обладает самой мощной поддержкой ОО технологии.

Кроме того, C++ поддерживает и другие, не объектно-ориентированные технологии программирования.

С++ универсальный язык, на нем можно написать и операционную систему, и информационную систему предприятия. С++ поддерживается международными стандартами и не зависит от какой-то одной фирмы.

Smalltalk

Smalltalk проповедует чистую ОО технологию и поддерживает только ОО технологию. Он также является интерпретатором и, программы, написанные на нем, работают не слишком быстро (что, вообще говоря, делает его не совсем универсальным). Smalltalk также как и C++ поддерживается международными стандартами и не зависит от какой-то одной фирмы.

TurboPascal

Начиная с 5-ой версии, TurboPascal стал объектно-ориентированным. Этот язык вполне поддерживает ОО технологию. Он постоянно перенимает у C++ все новое (естественно, с запозданием). В этом смысле он вторичен по отношению к C++. TurboPascal создала фирма Borland и он целиком от нее зависит. Насколько мне известно, никакими стандартами (ANSI, ISO) не поддерживается. Не известно, что с ним будет, если, например, фирма Borland обанкротится.



24 Окт 1997
Дмитрий Кищуков e-mail: d.kish@g23.relcom.ru

URL: http://geocities.datacellar.net/SiliconValley/Horizon/3810/tech-win.html 1