Категории
Самые читаемые
onlinekniga.com » Компьютеры и Интернет » Программирование » Как пасти котов. Наставление для программистов, руководящих другими программистами - Дж.Ханк Рейнвотер

Как пасти котов. Наставление для программистов, руководящих другими программистами - Дж.Ханк Рейнвотер

Читать онлайн Как пасти котов. Наставление для программистов, руководящих другими программистами - Дж.Ханк Рейнвотер

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 67 68 69 70 71 72 73 74 75 ... 77
Перейти на страницу:

Приложение Б

Как дать скотине в глаз – критический обзор кода электронного администратора

В главе 6, в разделе «Кодовая полиция», я объяснял, как стать кодовым полицейским. Сохранять объективность при чистке собственного кода очень сложно, но я постараюсь. Связав в названии этого приложения свой код со скотным двором, я надеялся подсказать вам, что я собираюсь делать. Все, что я хочу, – это чтобы вы разобрались в процессе критического обзора кода и обратили внимание на некоторые моменты, которые играют существенную роль в процессе проверки кода, написанного подотчетной вам группой.

Имея перед глазами исходный код, вам будет легче читать это приложение. Как я уже говорил в приложении А, скачать код можно с сайта http://www.piter.com.

Контекст и происхождение программного продукта

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

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

Правила игры

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

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

• Внутри объектов соблюдается строгая связность. Объект – это несколько больше, чем просто группа процедур; он должен выполнять конкретную функцию. Как известно, сердце не дышит, а легкие не качают кровь.

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

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

Следовал ли я стандартам?

В основном я следовал стандартам – по крайней мере, мне так кажется. VB я пользуюсь, начиная с версии 1.0, и с годами отношения с кодом складывались у меня (наверное, так же как и у вас) по-разному – был и удачный, и провальный опыт. С моей точки зрения, следование стандартам VB выражается в попытках привести объектно-ориентированные понятия в соответствие с этим языком, который, по правде говоря, отнюдь не полностью поддерживает объектно-ориентированную парадигму.

В главе 4 я изложил понятие задачи, или задания, – основного организующего принципа программного обеспечения. Просмотрев мой код, вы найдете в нем объект под именем clsTasks и вспомогательный объект clsTask. В этих двух модулях классов инкапсулированы пользовательское взаимодействие и все данные, обрабатываемые программой в связи с заданиями. Формы frmTask и frmTasks, ответственные за обработку заданий на стороне графического пользовательского интерфейса, являются дочерними объектами объекта clsTasks. Все прочие объекты, например clsToday, при обработке заданий обращаются к локальным экземплярам clsTasks. Эта схема довольно удачно, как мне кажется, иллюстрирует методику многократного использования объектов.

Модульные объявления объекта clsTasks выглядят так:

'-Закрытые объекты и события

Private mo_DataService As clsDataService '–данные объекта

Private mo_PickList As clsPickList '–список отбора для форм

Private WithEvents mfjasks As frmTasks '–все задания, связанные с frmTasks

Private WithEvents mfjask As frmTask '–отдельное задание, связанное с frmTask

Private mo_DataGrid As DataGrid

Private WithEvents mo_DataProvider As clsDataProvider '–основные данные

Private ml_CurTaskID As Long '–выбранный идентификатор задания

Private ms_Project As String '–применяется с frmProject

Private mo_ProgConfig As clsProgConfig

Private ms_TaskFilter As String

Private mo_Task As clsTask

Private mb_NeedRefresh As Boolean

Private ms_Resource As String

Private ms_Source As String '–открытые объекты и события

Public Event TaskUpdatedO

И что мы имеем? Много комментариев, среди которых нет ни одного, который описывал бы назначение центрального объекта. Плохой код и бездарный кот! И каким же образом человек со стороны сможет понять, зачем этот объект нужен, если нет никаких описаний?! Для этого придется основательно изучать код. Я-то его знаю вдоль и поперек, а вот свежий взгляд наткнется на труднопреодолимое препятствие.

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

Нельзя, однако же, не признать некоторые достоинства вышеприведенного фрагмента кода. Обратите внимание на имена переменных – m в них идентифицирует область действия (модуль), а следующий символ обозначает тип переменной (Соответствует длинной переменной, s – строковой, b – логической, и т. д.).

Теперь рассмотрим конкретную процедуру, инициирующую процесс отображения формы задания:

Public Sub Show(Optional sResource As String ="")

If (mf_Tasks Is Nothing) Then

SetHourglass

Set mf_Tasks = New frmTasks Load mfjasks

Set mo_DataGrid = mf_Tasks .grdTasks

'-load tasks

LoadTaskGrid

'-Load resource combo

mo_PickList.LoadPickList mf_Tasks.cboResource. PIC_RESOURCE

' -configure task list

ms_Resource = sResource

mf_Tasks.Configure ms_Resource

If sResource «» "" Then   ' -установка источника данных для отображения отдельного задания

ms_TaskFilter = "Assigned =" & Chr$(39) & sResource & Chr$(39)

mo_DataProvider.Filter ms_TaskFi1ter

mo_DataProvider.Sort «Status»

End If

SetReady

End If

With mf_Tasks

WindowState = 0

Show

ZOrder 0

End With

End Sub

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

Как насчет связности и взаимозависимости?

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

Программа управляется объектом clsApplication с глобальной областью действия. Из него создаются и управляются на высоком уровне все остальные объекты. К примеру, в процедуре с понятным именем cLsAppLication.StartApplication создана родительская форма MDI и ряд других вспомогательных объектов. С точки зрения процесса исполнения программы это сугубо положительный момент.

Объявления модулей в clsApplication выглядят так:

Private WithEvents mf_Parent As nidiManager

Private WithEvents mo_Projects As clsProjects

Private WithEvents mo_Tasks As clsTasks

Private WithEvents mo_Today As clsToday

Private WithEvents mo_Archive As clsArchive

Private mo_Contacts As clsContacts

Private mo_DataService As clsDataService

Private mo_Reports As clsReports

Private mo_ProgConfig As clsProgConfig

Private mo_PickList As clsPickList

Private mc_Tasks As New Collection '–коллекция объектов clsTasks

Private mc_Projects As New Collection '–коллекция объектов clsProjects

Private mc_Sources As New Collection '–коллекция объектов clsSource

Private moJJser As clsUser

Private mo_Source As clsSource

Private ms_DSN As String 'применяется при подключении

Здесь, если не считать нехватки комментариев уровня модуля, присутствуют все дочерние объекты clsApplication. Из этого фрагмента кода в принципе можно вывести всю объектную иерархию программы.

Реализация в программе многочисленных событий заметно «стройнит» код форм. В большинстве случаев родителями форм выступают модули классов, причем имена форм явственно свидетельствуют об этих отношениях. К примеру, clsProjects запускает frmProjects; впоследствии, если в форме происходит какое-то событие, его аналог сразу запускается в родительском элементе управления. Таким образом, код по большей части локализуется, что, в свою очередь, способствует инкапсуляции.

1 ... 67 68 69 70 71 72 73 74 75 ... 77
Перейти на страницу:
На этой странице вы можете бесплатно читать книгу Как пасти котов. Наставление для программистов, руководящих другими программистами - Дж.Ханк Рейнвотер.
Комментарии