И что мы имеем? Много комментариев, среди которых нет ни одного, который описывал бы назначение центрального объекта. Плохой код и бездарный кот! И каким же образом человек со стороны сможет понять, зачем этот объект нужен, если нет никаких описаний?! Для этого придется основательно изучать код. Я-то его знаю вдоль и поперек, а вот свежий взгляд наткнется на труднопреодолимое препятствие.
Будь вы менеджером, вы бы, конечно, настояли на введении заголовка модуля с указанием его автора и даты создания. Кроме того, вы, вероятно, потребовали бы от программиста составить обзор модуля, обозначив в нем имена открытых процедур и механизм «жизнеобеспечения» ими объекта.
Нельзя, однако же, не признать некоторые достоинства вышеприведенного фрагмента кода. Обратите внимание на имена переменных – 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; впоследствии, если в форме происходит какое-то событие, его аналог сразу запускается в родительском элементе управления. Таким образом, код по большей части локализуется, что, в свою очередь, способствует инкапсуляции.