[ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Источники | >>> ]
© 2001 А.И. Легалов
Мне нравится объектно-ориентированное программирование (ООП). Доставляет удовольствие процесс формирования каркаса приложения на основе базовых классов и дальнейшая раскрутка его, с применением механизма наследования. Это не отступные, вызванные саркастическим тоном предыдущего материала. Это действительно так. Истинно объектные механизмы обеспечивают, при определенных условиях, эффективное конструирование.
Но мне нравится и процедурное программирование (ПП): своим четким разделением программных объектов на данные и процедуры, ясными и понятными концептуальными моделями, возможностью независимой функциональной декомпозицией и такой же декомпозицией данных, сочетаемых и совмещаемых на каждом шаге проектирования (чего обычно не хотят замечать поверхностные апологеты ООП [King], акцентируя критику только на функциональной декомпозиции).
Поэтому, я программирую на C++, который позволяет гармонично сочетать оба подхода. Этим давно пользуются специалисты, например Скотт Мейерс [Мейерс2000-1, Мейерс2000-2]. Он описал много эффективных приемов, обеспечивающих использование как чисто ОО стиля, так и его сочетаний с процедурным подходом, правда, явно не выделяя использование последнего [Meyers]. Думаю, что C++ будет еще долго оставаться одним из основных инструментов нашей рабочей группы (по крайней мере, до того момента, пока не будут созданы языки и трансляторы, более полно удовлетворяющие предъявляемым нами требованиям:).
Помимо этого я прекрасно отношусь к функциональному стилю. До сих пор считаю это направление одним из перспективных, особенно в области параллельного программирования.
Во многом это происходит оттого, что я рассматриваю программирование как искусство, являющееся предметом анализа. Стили программирования интересны мне сами по себе, а не конечным результатом, определяемым разработанной программой. А изучение техники программирования, во многом, определяемой парадигмами, - мое хобби. Исходя из этих рассуждений я и пытаюсь играть роль "искусствоведа", "восхваляя" то, что мне нравится, и критикуя то, что "не воспринимаю". Естественно, что получаемые оценки носят субъективный характер, не смотря на попытки объективно разобраться в сложившейся ситуации. Опираясь на эту позицию, я пытаюсь далее проанализировать основные черты парадигм программирования.
Подобное восприятие предметной области относится не только к парадигмам. В меньшей степени (хотя, и не такой уж и малой:) меня интересуют методологические и архитектурные аспекты программирования, между которыми находятся парадигмы. Именно такое промежуточное положение и определяет основные задачи стилей: служить средством преодоления семантического разрыва между архитектурами вычислительных систем и разработчиками программного обеспечения. А здесь, на мой взгляд, только одного ООП или ПП сейчас недостаточно.
Проведем ассоциацию программирования с человеком. Пусть ООП будет его правой рукой, а ПП - левой (можно и наоборот, но многие почему-то ассоциируют ООП с мышью, которая чаще располагается под правой рукой:). Отрежьте человеку одну руку, и он сможет со временем научиться выполнять функции, осуществляемые ранее отсутствующей рукой. Только это будет менее эффективно. Вот потому я с предубеждением отношусь к чисто объектным средствам и языкам программирования (Java, C#), предпочитая им "громоздкий и избыточный" C++. Нельзя нормально программировать, не используя при этом всех имеющихся знаний. Работа Скотта Мейерса [Meyers], перевод которой лежит на моем сайте, лишний раз подтверждает это. Поэтому, когда знатоки Java и C# говорят, что эти языки являются подмножеством C++, из которых убрали все лишнее, я судорожно начинаю соображать: какую руку мне отрезать, а какую дополнительно обучить (я, от природы, праворукий левша: правой рукой пишу, а левой - рисую).
Меня также не убеждают аргументы, что "урезанные" языки легче для изучения, а "однорукое программирование" порождает более надежный код. Во-первых, я достаточно долго изучал программирование вообще и C++ в частности, чтобы верить, что надежность определяется только языковыми средствами. Кроме чистого кодирования необходимо еще и формирование соответствующей культуры, которая складывается годами. Посмотрите, сколько книг и статей посвящено именно культуре программирования на C++. Почитайте "Дизайн и эволюцию C++" [Страуструп2000], в которой четко прослеживается идея создания языка, обеспечивающего поддержку "правильного" и "неправильного" программирования. А чему учат книги, посвященные "самым современным" языкам? По-моему, искусству манипуляции с мышью (еще одна однорукая ассоциация:).
Во-вторых, культура программирования во многом не зависит от того языка, на котором приходится писать программы. Кроме чистого кодирования и рисования форм существует еще множество других технологических пластов, которые необходимо взрыть, осознать и применить. И никакой, даже самый современный язык программирования, ориентированный на использование любых компонент, сам по себе не обеспечит создание надежного и эффективного приложения.
Поверьте, я ничего не имею против визуального конструирования, компонент, волшебников, экспертов, мастеров, библиотек классов и прочих средств, обеспечивающих быстрое наращивание дополнительной функциональности приложений. Конечно, можно сразу сесть за компьютер и слепить из готовых компонент программу. Однако, это совершенно другая тема, требующая отдельного разговора. Она мало касается техники кодирования и практически не соприкасается с рассматриваемыми ниже вопросами. Любое из названных выше средств может быть разработано с использованием как объектно-ориентированного, так и любого другого стиля. Они могут применяться при разработке объектно-ориентированных и процедурных программ. Не я написал критику библиотеки классов MFC за отсутствие объектной ориентации. Не я разработал модель компонентных объектов (COM) таким образом, чтобы компоненты прекрасно создавались с использованием как процедурных, так и ОО языков [Роджерсон]. Популярность этих инструментов просто лишний раз показывает, что повышать эффективность программирования можно различными способами, в том числе, и расширением функциональных возможностей программных объектов, используемых в качестве базовых строительных блоков.
Хотелось бы также подчеркнуть, что представленный материал посвящен технике программирования (кодирования), а не сравнительному анализу языков. Поэтому, не затрагиваются особенности синтаксиса и семантики, наличия или отсутствия различных бантиков. Над любым из языков можно глумиться, но почти на любом из них можно писать прекрасные программы.
Но "вернемся к нашим баранам". "Противостояние" между сторонниками ОО и прочих стилей напоминает мне стычки между Линуксоидами и Виндовозниками. Но не содержанием перепалок, а качественным составом "противоборствующих" сторон.
ОО программисты видятся как чернокнижники-интеллектуалы, познавшие таинства магических заклинаний собранных по крупицам из сотен книг и сайтов. Выстраивая вокруг себя непонятные диаграммы классов и оживляя их магическими словами (класс, паттерн, UML...), они постепенно строят огромное чудище путем эволюционного добавления к нему все новых и новых кусков.
Процедурные программисты - это сторонники быстрых решений, которым ничего не стоит слепить программу, тут же разломать ее и перелепить заново, если что-то не понравилось. Им не нужна крепость, так как они не ждут волка. Достаточно иметь соломенную хижину Ниф-Нифа. И неважно, какой язык программирования при этом используется: процедурный или объектно-ориентированный.
Если же говорить серьезно, то коренным же отличием этих двух групп является ориентация на разработку приложений различного объема и сложности, что ведет к разным методологическим и техническим решениям. Именно использование технических решений, обеспечивающих эволюционное расширение уже написанного кода, следовать которым необходимо от начала и до конца проекта, определяет всю таинственность и громоздкость объектно-ориентированного программирования. Недостаточно просто выучить соответствующий язык. Необходимо еще овладеть множеством методов и приемов, определяющих правильное использование изученных конструкций. Вот почему объектно-ориентированное проектирование постоянно сопоставляется с архитектурой, а методы Кристофера Александра нашли широкое понимание и поддержку [Appleton, Гамма].
Вместе с тем, большинство приложений не требуют тщательного проектирования, а также повторного использования. Поэтому и существуют программисты, которым безразличны ритуальные танцы вокруг разрабатываемой программы. Зачастую здесь нет ничего плохого: зачем дополнительно выкладываться в обучение проектированию при написании серии слабо взаимосвязанных скриптов, манипулирующих высокоуровневыми конструкциями и доступными компонентами? Не важна также и принадлежность языка программирования к определенной парадигме.
Окончательно зафиксировать высказанные предположения мне хочется еще одной простенькой ассоциацией. Предположим, что надо написать программу (возможно, небольшую), осуществляющую перевозку груза из пункта A в пункт B. Обычный программист обратит все свое внимание на достижение окончательного результата, не задумываясь особо над вариациями, возможными при повторном решении этой же задачи. Скорее всего, его программа будет написана быстро и успешно справится с поставленной проблемой. ОО программист начнет выстраивать "дорогу жизни", изначально предусматривая объездные пути возможных преград и ловушек, которых в действительности может и не оказаться. Естественно, что такое программирование займет больше времени. Однако, если вслед за этой задачей, появится новая, определяющая перевозку из C в D, но при других условиях, ОО программист начнет пожинать плоды со своей предусмотрительности. У Скотта Мейерса, по этому поводу, даже есть правило под номером 32: "Программируйте, заглядывая в будущее" [Мейерс2000-2].
Таким образом, объектно-ориентированное программирование - это не только соответствующий язык. Это еще и образ мышления, направленный на создание эволюционирующих программ.
[ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Источники | >>> ]