Лекция вторая. Что такое хорошо

(редакция от 08.05.86)

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

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

Обычно программисты считают программу хорошей, если она быстро отлаживается. Такое понимание весьма узко, и я бы даже сказал, эгоистично. В самом деле, неприятно, если твоя программа долго отлаживается : это означает, что нужно что-то делать, возиться с ней, а если не сдашь в срок - сами понимаете, нет зачета по курсовой , нет премии, и так далее, и тому подобное. Очевидно, что это свойство программы существенно для того, кто ее пишет (хотя, конечно, тот, кто ею пользуется, тоже не прочь получить ее пораньше, если она ему действительно нужна). Но, даже если хорошая программа понимается именно так, программисты все-таки ведут себя удивительно. Несмотря на то, что жизнь постоянно щелкает программистов по носу, они , начиная очередную программу, почему-то всегда уверены, что она обязательно будет хорошей и отладится очень быстро. Каждая ошибка их безмерно удивляет и кажется последней. Жалобы пользователей на неэффективность, негибкость, ненадежность, неудобность и прочие "не-".тоже кажутся программистам странными - ведь, когда программа писалась, она была такой хорошей!

Программировать нужно не так.

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

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

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

Задумаемся над словами "программа делает то, что нужно". Нужно кому?

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

Тогда, может быть, программа делает то, что нужно, если она делает то, что от нее хотел руководитель (или будем говорить "разработчик")? Но и это не так! Программный продукт делается не для себя, а для некоего заказчика (а программное изделие - и вообще для некоей группы потенциальных пользователей). Заказчик - это человек (или группа людей) , который определяет функции будущего программного продукта. У него есть свои представления об этом продукте, а у разработчика - свои, и нетрудно догадаться, что они совсем не обязательно совпадают, даже если и заказчик, и разработчик уверены в обратном и считают, что они прекрасно друг друга поняли.

Ну, тогда, видимо, следует считать, что программа делает то, что нужно, если на делает то, что от нее хотел заказчик?

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

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

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

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

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

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

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

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

1.Соответствие нуждам пользователя

2.Удобство в работе (или, как говорят, учет человеческого фактора)

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

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

3.Надежность (можно разделить это свойство но два):

3.1.Отсутствие ошибок (т.е. правильная работа в правильной среде)

3.2.Безопасность,т.е. защита от неправильного использования

Чего еще вправе ждать пользователь от программного продукта? Он вправе ждать от него умеренной траты машинных ресурсов. не говоря уже о том, что это существенный экономический показатель, и не говоря уже о том, что иногда время или память являются критическими ресурсами (хороша была бы система "сирена", если бы она обрабатывала запрос на авиабилет минут пятнадцать!); не говоря уже об этом, эффективность часто бывает связана с удобством. вот пример : есть у нас замечательная программа-документатор, с помощью которой набирался и текст лекций спецкурса. Она очень удобна в использовании, но берет больше двухсот килобайт памяти, и на нашей старушке ЕС-1022 это означает, что работать с этим документатором можно только по выходным и вечерами, поскольку днем выкроить 200 килобайт - бесполезное занятие.

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

4.Эффективность

И, наконец, еще одно свойство хорошего программного продукта, которое в условиях нынешнего разнообразия вычислительной техники и калейдоскопа операционных систем оказывается довольно существенным. Программа должна работать на возможно большем диапазоне технических и программных средств. Вот простой пример : все работали у нас на одной ЕС-1022, и вот некая лаборатория получила СМ-4. Считать на ней несравненно удобнее, учитывая хлипкость и перегруженность ЕС, и естественно, что сотрудники этой лаборатории тут же ЕС-ку покидают. Но, хотя по программистской присказке, фортран и в Африке - фортран, но размер слова у ЕС и СМ разный, и если, например, в программе вычисления минимума мы присваиваем сначала минимуму максимальное число, представимое в машине - 7.2е75, то для СМ это уже будет ошибкой : такое число просто не поместится в слове. Если это возможно, следует писать программу, не используя особенности данной машины.

Поэтому запишем еще одно свойство хорошей программы :

5.мобильность

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

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

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

Разве можно писать программу, не понимая ее - спросите вы. Еще как можно! Доводилось ли вам в школе писать сочинения на темы, о которых у вас самые смутные представления? Вот так же часто пишутся и программы. Я это говорю вполне обоснованно : долгое время я консультировал программистов и очень часто видел, как они пытались понять то, что сами написали. Запишем :

6.Понятность

Что нужно сделать для того, чтобы программа была понятна?

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

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

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

Ну, я думаю, что пока о понятности хватит - на эту тему у нас впереди целая лекция, а сейчас рассмотрим еще одно свойство хорошего программного продукта:

7.модифицируемость.

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

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

С того момента, как в 1979 году мы сдали первую работоспособную версию системы ДЕЛЬТА, мы занимаемся исключительно ее расширением и модификациями. Каждый новый пользователь выдает ворох своих предложений, плюс к тому нас самих обуревают идеи, да и техника развивается, появляются новые возможности. В наших программах осталось 20-30 процентов первоначального текста. Существуют методы написания программ, облегчающие внесение изменений, и этому также будет посвящена отдельная лекция.

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

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

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

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

9.Технологичность, т.е. наличие не только программ, но и процедур восстановления, настройки и т.д.

Итак, мы выписали свойства хорошего программного продукта:

1.соответствие нуждам пользователя

2.удобство в работе и обслуживании

3.надежность, т.е. отсутствие ошибок и живучесть

4.эффективность

5.мобильность

6.понятность

7.модифицируемость

8.неприхотливость

9.технологичность

Это и есть цели, к которым нужно стремиться при разработке программного продукта. Поэтому весь спецкурс будет строиться так : о чем бы мы ни говорили, мы всегда будем иметь в виду эти цели. Разбираем ли мы какой-нибудь подход мы должны оценить, как он соотносится с этими свойствами. Рассматриваем ли мы какой-либо проектный документ - прежде всего мы должны понять, насколько использование такого документа позволить достичь этих целей.

На оглавление


© Алексей Бабий 1980-1986