CHAP1 (1018801)
Текст из файла
Глава
1
Процесс проектирования
Эта глава вместе с последующей, посвященной разработке, являются наиболее туманными главами в этой книге. Правила здесь довольно общего характера по своей природе, они совсем не затрагивают техники программирования на С или С++, а скорее рассматривают более общий процесс проектирования и разработки программы.
Правила из данной главы относятся к процессу общего проектирования. После прочтения этой главыи в законченном виде я стал беспокоиться, что многие из этих правил будут казаться банальными. Несмотря на это, некоторые из приводимых здесь правил являются самыми важными в этой книге, потому что нарушение их может вызвать много бед в процессе разработки. В известном смысле, многие из правил в этой главыи предназначены для управленцев; программисты их часто знают, но у них нет свободы, необходимой, чтобы воспользоваться своими знаниями.
1. Сущность программирования: без сюрпризов, минимум сцепления и максимум согласованности.
Многие (если не все) правила в этой книге могут быть объединены в три метаправила (при желании), выраженные в заголовке этого раздела.
Правило "без сюрпризов" не требует пояснений само по себе. Пользовательский интерфейс должен действовать так, как кажется он должен действовать. Функция или переменная должны делать то, что означают их имена.
Сцепление - это связь между двумя программами или объектами пользовательского интерфейса. Когда один объект меняется, то все, с чем он соединен, может также измениться. Сцепление способствует сюрпризам. (Я меняю эту штучку здесь, и внезапно та штуковина вон там перестает работать). Пример из С++: если объект одного класса посылает сообщение объекту второго класса, то посылающий класс сцеплен с принимающим классом. Если вы меняете интерфейс для принимающего класса, то вы также должны исследовать код в посылающем классе, чтобы убедиться в том, что он еще работает. Этот вид слабого сцепления безвреден. Вам нужно знать об отношениях сцепления для сопровождения программы, но без некоторого количества сцеплений программа не могла бы работать. Несмотря на это, для вас желательно по мере возможности минимизировать число отношений сцепления.
Эта минимизация обычно выполняется в С посредством модулей, а в С++ посредством классов. Функции в модуле (функции-члены в классе) сцеплены друг с другом, но за исключением нескольких интерфейсных функций (или объектов) они вовсе не сообщаются с внешним миром. В С вы должны использовать статический класс памяти, чтобы ограничить использование функции одним модулем. В С++ вы используете закрытые функции-члены.
Согласованность является противоположностью сцепления; сущности, которые группируются вместе (пункты диалогового и простого меню, функции в модуле, или члены класса), должны быть связаны по назначению. Отсутствие связности также является "сюрпризом". У текстового редактора, которым я пользуюсь, имеется в меню пункт "Настройка" и, кроме того, дополнительные опции настройки рассыпаны по четырем другим всплывающим меню. Я ожидал согласованной конфигурации и, когда не смог найти нужную мне опцию в пункте "Настройка", то решил, что этой опции просто нет. Эта плохо спроектированная система до сих пор доставляет беспокойство; после года пользования я по-прежнему не помню, где расположена каждая опция, и часто вынужден тратить раздражающие пять минут на поиск в пяти разных местах того, что хотел изменить. По отношению к исходному коду отсутствие согласованности заставляет вас делать то же самое - тратить свою жизнь на поиск объявлений функций в 15 различных файлах, что является очевидной проблемой при сопровождении.
2. Подавляйте демонов сложности (Часть 1).
Ричард Рашид (разработчик Mach - варианта ОС UNIX) выступил несколько лет назад с основным докладом на конференции разработчиков Microsoft. Его главный смысл состоял в том, что слишком большая сложность как в пользовательском интерфейсе, так и в программе является единственной большой проблемой, стоящей перед проектировщиками и пользователями программного обеспечения. По иронии, его речь была произнесена спустя два дня после провалившейся попытки показать нескольким тысячам очень толковых программистов, как программировать разработанный Microsoft интерфейс OLE 2.0 - один из самых сложных интерфейсов прикладного программирования, когда-либо мной виденных. (OLE означает "связь и внедрение объектов". Стандарт OLE 2.0 определяет интерфейс, который может использоваться двумя программами для взаимодействия между собой определенным образом. Это действительно объектная ориентация на уровне операционной системы).
Предыдущий оратор, который убеждал нас пользоваться библиотекой Microsoft Foundation Class (MFC), сказал нам, что поддержка OLE в MFC "включает 20000 строк кода, необходимых для каждого базового приложения OLE 2.0". Аудитория была ошеломлена не полезностью MFC, а тем фактом, что для написания базового приложения OLE 2.0 требуется 20000 строк кода. Любой интерфейс такой сложности таит в себе изъян. Следующие несколько правил используют OLE для показа характерных проблем, но не думайте, что проблема запутанности характерна лишь для Microsoft - она свойственна всей отрасли.
2.1. Не решайте проблем, которых не существует.
2.2. Решайте конкретную проблему, а не общий случай.
Поучительно использовать OLE 2.0 как пример того, что случается с многими слишком сложными проектами. Имеется две главные причины сложности интерфейса OLE. Во-первых, он безуспешно пытается быть независимым от языка программирования. Идея таблицы виртуальных функций С++ является центральной для OLE 2.0. Спецификация OLE даже пользуется нотацией классов С++ для документирования того, как должны работать различные интерфейсы OLE. Для реализации OLE на другом языке программирования (не С++) вы должны имитировать на этом языке таблицу виртуальных функций С++, что фактически ограничивает ваш выбор С++, С или языком ассемблера (если вы не разработчик компиляторов, который может добавить к выбранному вами языку нужные свойства). Если честно, то вы должны быть сумасшедшим, чтобы программировать OLE не на С++; потребуется гораздо меньше времени на изучение С++, чем на написание имитатора С++. То есть, эта идея независимости от языка программирования является неудачной. Интерфейс мог бы быть существенно упрощен за счет отказа от нее.
Возвращаясь к истории из предыдущего раздела, нужно заметить, что библиотека MFC в действительности решает проблему сложности, связанную с OLE, при помощи простого и легко понятного интерфейса, реализующего все возможности, нужные для большинства приложений OLE 2.0. Тот факт, что никто не хотел программировать с использованием OLE, пока для этого не появилась оболочка на основе MFC, впечатляет. Разработка хорошей оболочки вокруг плохого интерфейса не может быть решением лежащей в основе проблемы.
Если оболочка с использованием MFC столь проста, то почему лежащий в основе пласт так сложен? Ответ на этот вопрос является основным предметом проектирования. Создатели интерфейса OLE никогда не задавали себе два основных вопроса:
-
Какие основные возможности должно поддерживать настоящее приложение?
-
Как реализовать эти возможности простейшим способом?
Другими словами, они имели в виду не реальное приложение, когда они проектировали этот интерфейс, а какой-то теоретический худший случай. Они реализовали самый общий интерфейс из возможных, не думая о том, что на самом деле предполагается делать при помощи этого интерфейса, и получив в результате систему, которая может делать все, но при этом слишком сложная, чтобы быть пригодной для использования. (Вероятно, они совсем не пробовали реализовать этот интерфейс в каком-либо приложении, иначе бы обнаружили эти проблемы).
Процесс объектно-ориентированного проектирования является в какой-то мере попыткой решения этой проблемы. Относительно просто добавить новую возможность в объектно-ориентированную систему или посредством наследования, или добавив новых обработчиков сообщений к существующим классам. Скрывая определения данных от пользователя класса, вы оставляете за собой право полностью менять внутреннюю организацию класса, включая определения данных, не беспокоя пользователей этого класса, при условии, что вы сохраняете его существующий интерфейс.
В структурном проектировании вы не стараетесь иметь такую роскошь. Вы обычно проектируете сперва структуры данных, и модификация структуры данных является главным делом, потому что нужно проверить каждую подпрограмму, использующую эту структуру данных, чтобы убедиться в том, что она еще работает. Как следствие, "структурные" программы склонны иметь много ничего не делающего кода. Это потому, что кто-нибудь может захотеть воспользоваться некой возможностью в будущем. На деле многие проектировщики структурных программ горды своей способностью предсказывать направление, в котором может развиваться программа. Все это приводит к большому объему ненужной работы и программам, имеющим больший размер, чем необходимо.
Вместо того, чтобы учитывать в проекте все возможные случаи, проектируйте свой код так, чтобы он мог быть легко расширен при необходимости добавления новых возможностей. Объектно-ориентированные проекты, как правило, тут работают лучше.
3. Интерфейс пользователя не должен быть похожим на компьютерную программу (принцип прозрачности).
Я однажды слышал, как кто-то сказал, что лучшим пользовательским интерфейсом из когда-либо разработанных является карандаш. Его назначение тотчас же понятно, для него не нужно руководство пользователя, он готовится к работе без особой суеты. Однако наиболее важным свойством является прозрачность. Когда вы пользуетесь карандашом, то думаете о том, что вы пишите, а не о самом карандаше.
Подобно карандашу, лучшими компьютерными интерфейсами являются те, которые скрывают сам факт того, что вы обращаетесь к компьютеру: замечательный пример - интерфейс с системой зажигания вашего автомобиля. Вы поворачиваете зажигание, включаете скорость и жмете на газ, как если бы все эти объекты интерфейса (ключ, рычаг скоростей, педаль) были прицеплены прямо на двигатель. Тем не менее, это не так: они теперь обычно просто устройства ввода в компьютер, который управляет двигателем.
К сожалению, подобный уровень ясности часто отсутствует в пользовательских интерфейсах. Представьте графический интерфейс пользователя Wimdows на автомобиле. Вы трогаетесь, выбрав в главном меню пункт "Движение автомобиля". Щелчок по нему откроет меню "Переключение скорости", которое предложит вам выбор из опций "Вперед", "Назад" и "Нейтральная". Щелкните по одной из них, чтобы передвинуть флажок на нужное вам направление. Затем вернитесь в меню "Движение автомобиля" и выберите команду "Поехали". Это вызовет появление диалогового окна "Скорость", где вы должны использовать ползунок для ввода желаемой скорости. Однако установить скорость правильно трудно вследствие высокого разрешения ползунка (пол-миллиметра движения мыши соответствует примерно 1 км/ч), поэтому вы скорее установите 59,7 км/ч вместо 60. Затем вы нажимаете кнопку "Поехали" в диалоговом окне, вслед за чем появляется сообщение "Стояночный тормоз не убран - нажмите F1 для справки" (динамик издает громкий звук). Вы покорно щелкаете по кнопке "ОК", чтобы убрать окно сообщений, затем снова пытаетесь открыть главное меню, но машина просто посылает вам звуковой сигнал. Наконец, поняв, что дело в том, что диалоговое окно "Скорость" еще отображается, вы щелкаете по кнопке "Отмена", чтобы убрать его. Вы открываете меню "Стояночный тормоз" и убираете флажок "Включен". Затем вы снова открываете окно "Поехали". И вновь получаете сообщение (и громкий звук) о том, что вы должны сначала выбрать направление в меню "Переключение скорости". В этот момент вы решаете, что вам, может быть, лучше пройтись на работу пешком.
Вот другой пример: Занимаясь недавно подготовкой обзора, я просмотрел несколько программ авиационных бортовых журналов. ("Бортовой журнал" - это очень простой табличный документ. Каждая строка соответствует отдельному вылету, а столбцы разбивают общую продолжительность вылета на различные категории: итоговая продолжительность, продолжительность полета в облаках и т.п.. В других столбцах полет помечается как деловой и так далее).
Самый лучший интерфейс из всех был тот, который выглядел совершенно одинаково с привычным бумажным журналом, но автоматизировал нудную работу. Вы вводили время в "итоговый" столбец - и то же самое время появлялось в других подходящих по смыслу столбцах. Значения по столбцам складывались автоматически для получения итогов по категориям. Вы могли легко генерировать необходимые отчеты и экспортировать данные в формат ASCII с разделителями из символов табуляции, который читается поистине любой программой электронных таблиц или подготовки текстов в мире. Для непривычного взгляда весь интерфейс казался, мягко говоря, разочаровывающим, но он был функциональным и интуитивно понятным, а программа - маленькой и быстрой. Однако самым важным было то, что этот интерфейс выглядел как бортовой журнал, а не как программа для Windows.
Другой крайностью был ошеломляющий графический интерфейс пользователя Windows: у него были диалоговые окна; у него была трехмерная графика; вы могли генерировать круговые диаграммы, показывающие процент продолжительности полета в облаках по отношению к вашему общему налету на "Цесне-172" за последние 17 лет; вы могли помещать внутрь отсканированную фотографию самолета...- вы представили эту картину. Программа выглядела превосходно, но ее было почти невозможно использовать. Не было практической причины для создания большинства диаграмм и отчетов, которые она могла генерировать. Ввод данных был неудобный и медленный - вы должны были вызвать диалоговое окно с полями, разбросанными по всей его поверхности. Фактически вы должны были прочитать все, чтобы обнаружить ту категорию, которая вас интересовала, а некоторые из категорий были скрыты за кнопками, неизбежно влеча за собой сложный поиск. Чтобы добавить обиду к оскорблению, эта программа была надстроена над сервером реляционной базы данных (помните, что это для поддержки простой таблицы без реляционных связей). Она заняла 30 Мбайт на моем диске. Мне требовалось почти 5 минут, чтобы сделать запись, которая занимала примерно 10 секунд в бумажном бортовом журнале или упомянутом ранее простом графическом интерфейсе пользователя. Программа была бесполезна, но, конечно, потрясающа.
Одна из главных проблем заключалась в том, что инструменты, использованные для создания второй программы, перегружают проектирование интерфейса. Все эти программы были разработаны на языке очень высокого уровня Visual Basic (который мне на самом деле не очень нравится, между прочим). Приложения, созданные при помощи таких построителей приложений, как Visual Basic (или Power Builder, или Delphi, или ...) обычно имеют специфический внешний вид, который немедленно говорит вам, что за инструмент был использован для построения этого приложения. Проектировщику интерфейса некуда обратиться за помощью, если этот специфический вид не подходит для конкретного проекта. Пользователи генераторов приложений должны иметь их несколько на выбор, чтобы затем использовать тот, который лучше всего соответствует потребностям данного интерфейса. Не смотря на это, мой опыт показывает, что наиболее практические программы со временем (в конце концов) должны перенести по меньшей мере часть кода интерфейса на язык низкого уровня типа С или С++, поэтому важно, чтобы ваш генератор приложений был способен также использовать низкоуровневый код.
4. Не путайте легкость в изучении с легкостью в использовании.
Характеристики
Тип файла документ
Документы такого типа открываются такими программами, как Microsoft Office Word на компьютерах Windows, Apple Pages на компьютерах Mac, Open Office - бесплатная альтернатива на различных платформах, в том числе Linux. Наиболее простым и современным решением будут Google документы, так как открываются онлайн без скачивания прямо в браузере на любой платформе. Существуют российские качественные аналоги, например от Яндекса.
Будьте внимательны на мобильных устройствах, так как там используются упрощённый функционал даже в официальном приложении от Microsoft, поэтому для просмотра скачивайте PDF-версию. А если нужно редактировать файл, то используйте оригинальный файл.
Файлы такого типа обычно разбиты на страницы, а текст может быть форматированным (жирный, курсив, выбор шрифта, таблицы и т.п.), а также в него можно добавлять изображения. Формат идеально подходит для рефератов, докладов и РПЗ курсовых проектов, которые необходимо распечатать. Кстати перед печатью также сохраняйте файл в PDF, так как принтер может начудить со шрифтами.















