1. ФАЙЛЫ ИСХОДНОГО КОДА

1.1. СТРУКТУРА ПАПОК ПРОЕКТА *

Рекомендуется, чтобы каждый проект создавался в папке "C:\Projects\Наименование проекта". Это позволяет избежать проблем с доступом к локальной копии проекта другим разработчикам. Также подобный подход позволяет избежать изменения настроек с абсолютными путями.

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

В проектах применяется следующая общепринятая структура папок:


|--Наименование проекта
       |- Art
       |- Bin
       |- Data
       |- Doc
       |- Exchange
       |- Includes
            |- Reports
            |- Scripts
       |- Setup
       |- Source
            |- <Исходники логической единицы 1..>
            |- <...>
            |- <Исходники логической единицы n..>
            |- Reports
            |- Scripts
            |- Shared
            |- SQL
       |- Tables
       |- ThirdParty

Верхний уровень: Наименование проекта.

Второй уровеньОписание
ArtСодержит различные мультимедийные элементы, используемые в проекте, в частности, графические элементы (иконки, заставки, фон и т.д.). Может содержать как стандартные элементы, так и разработанные специально для конкретного проекта
BinСодержит скомпилированные исполняемые файлы проекта, необходимые для его исполнения библиотеки. В данной папке также располагаются конфигурационные файлы. Папка может содержать вложенную папку Additional, в которой располагаются второстепенные по значимости бинарные файлы (просмотр содержимого файлов, импорт/экспорт данных и т.д.), в том числе, и разработанные третьей стороной.
DataСодержатся исходные данные, с помощью которых производится тестирование проекта, либо отдельных модулей на корректность.
DocСодержится документация к проекту. Может содержать вложенные папки, в которых размещена различная вспомогательная документация
ExchangeСодержится различная информация об открытых ошибках проекта, запланированных возможностях и т.д. Основное предназначение папки – обмен информацией между участниками проекта (сюда складываются письма, текстовые файлы и т.д. – данный метод дополняет систему управления проектами, но ни в коем случае не заменяет ее)
IncludesСодержатся файлы, которые должны распространяться вместе с скомпилированными исходными файлами проекта, однако используются также и в качестве исходных текстов (отчеты, скрипты и т.д.)
Reports – отчеты;
Scripts – скрипты.
SetupСодержится проект инсталлятора для проекта
SourceСодержатся исходники проекта, разделенные по отдельным приложениям, в частности здесь размещаются следующие папки:
Shared – модули, используемые несколькими приложениями одновременно. Если проект содержит общие модули, не являющиеся стандартными и выходящие за рамки проекта, то их копии необходимо разместить в данной папке, чтобы проект был самодостаточен.
SQL – содержатся скрипты, генерирующие БД проекта, скрипты, содержащие тестовые данные, примеры отдельных запросов. Здесь же размещены пакетные файлы (.bat или .cmd), вызвав которые можно сгенерировать БД проекта
Reports – отчеты, используемые в проекте.
Scripts – скрипты, используемые в проекте
TablesСодержится БД. Обычно несколько вариантов (резервные, разные версии, заполненные тестовыми данными и т.д.)
ThirdPartyСодержатся различные необходимые проекту вспомогательные приложения, материалы и т.д., разработанные третьей стороной и не являющиеся документацией.

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

1.2. ИМЕНОВАНИЕ ИСХОДНЫХ ФАЙЛОВ

Язык Delphi поддерживает длинные имена файлов. Если при создании имени Вы используете несколько слов, то необходимо использовать заглавную букву для каждого слова в имени: MyLongName.pas. Этот стиль оформления известен как InfixCaps или CamelCaps. Расширения файлов должны быть в нижнем регистре.

Если Вы осушествляете перевод заголовочных файлов C/C++, то паскалевский эквивалент должен иметь тоже самое имя и расширение PAS. Например Windows.pas. Если правила грамматики языка Delphi требуют объединения нескольких транслированных файлов в один, то используйте имя того файла, в который Вы вкладываете остальные. Например: если WinBase.h вкладывается в Windows.h, то результирующее имя будет Windows.pas.

Все файлы модулей, созданные в организации ХХХ должны иметь префикс ХХХ.

1.3. ОРГАНИЗАЦИЯ ИСХОДНЫХ ФАЙЛОВ

Все модули Delphi могут содержать следующие элементы в определенном порядке:

Для визуального разделения элементов между ними должна быть хотя бы одна пустая строка.

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


{************************************************************}
{                                                            }
{                 Модуль <Наименование модуля>               }
{       Copyright (c) 2004  <Наименование фирмы>             }
{               отдел/сектор                                 }
{                                                            }
{  Разработчик: ХХ ХХ                                        }
{  Модифицирован: ДД ММММ ГГГГ                               }
{  Версия:         X.Y.Z.K                                   }
{************************************************************}

unit Buttons;

1.4. ДИРЕКТИВЫ КОМПИЛЯТОРА

Глобальные для проекта директивы компилятора не следует напрямую включать в исходный код. Для этого следует воспользоваться определением включений и подключить глобальный для проекта файл с директивами компилятора.


{$I NX.INC}
interface

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


{$S-,W-,R-}
{$C PRELOAD}

interface

uses
  Windows, Messages, Classes, Controls, Forms, Graphics, StdCtrls, 
ExtCtrls, CommCtrl;

1.5. ДИРЕКТИВЫ УСЛОВНОЙ КОМПИЛЯЦИИ

Все директивы условной компиляции должны быть собраны в одном модуле ХХX.INC. Этот файл предназначен для определения глобальных директив. Оператор include должен быть помещен между ключевыми словами unit и interface. Никто не может модифицировать файл ХХX.INC по собственному желанию.

1.6. СЕКЦИИ ОПРЕДЕЛЕНИЯ ТИПОВ И КОНСТАНТ (CONST, VAR И TYPE)

Зарезервированные слова var, const и type всегда пишутся на новой строке и не допускают появления на этой же строке какого-либо текста.

Правильно

Type
  TMyType = Integer;

const
  MyConstant = 100;

var
  MyVar: Integer;

Неправильно

type TMyType = Integer;

const MyConstant = 100;

var MyVar: Integer;

Процедуры должны иметь только по одной секции type, const и var в следующем порядке:


procedure SomeProcedure;
type
  TMyType = Integer;
const
  ArraySize = 100;
var
  MyArray: array [1..ArraySize] of TMyType;
begin
  ...
end;

Секция реализации должна начинаться с ключевого слова implementation, затем объявление используемых модулей (Uses clause), затем любые включение файлов или другие директивы.


implementation

uses
  Consts, SysUtils, ActnList, ImgList;

{$R BUTTONS.RES}

1.7. КОПИРАЙТ И КОММЕНТАРИЙ. ПРИМЕР ЗАГОЛОВКА ДЛЯ МОДУЛЯ


{************************************************************}
{                                                            }
{                 Модуль ХХХ                                 }
{       Copyright (c) 2001  ООО ХХХХ                         }
{               отдел/сектор                                 }
{                                                            }
{  Разработчик: ХХ ХХ                                        }
{  Модифицирован: 25 июня 2001                               }
{  Версия:        1.0.0.1                                    }
{                                                            }
{************************************************************}

Следует обратить внимание на элементы заголовка:

Версия для модуля используется в том случае, если он является ключевым и/или часто модифицируется. Версия используется в таком же формате, как и для проекта в целом.

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

1.8. ОБЪЯВЛЕНИЕ МОДУЛЯ

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

unit MyUnit;

Этот модуль будет назван MyUnit.pas, когда он будет сохранен операционной системой.

1.9. ОБЪЯВЛЕНИЕ ИСПОЛЬЗУЕМЫХ МОДУЛЕЙ

Внутри модуля объявление используемых модулей должно начинаться со слова uses в нижнем регистре. Затем следуют наименования модулей с сохранением регистра символов:

uses MyUnit;

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


uses
	Windows, SysUtils, Classes, 
	Graphics, Controls, Forms, TypInfo,  // модули Delphi
	XХХMyUnit1, ХХXMyUnit2;              // модули ХХХ

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

1.10. ОБЪЯВЛЕНИЕ КЛАССОВ И ИНТЕРФЕЙСОВ

Объявление класса начинается с двух пробелов, затем идет идентификатор класса с префиксом Т в нотации InfixCaps. Ни в коем случае в исходных файлах Delphi нельзя использовать табуляцию:

TMyClass

Следом за идентификатором класса идет пробел, знак равенства, пробел и слово class в нижнем регистре:

TMyClass = class

Если необходимо определить родителя класса, то следует добавить открывающую скобку, имя класса-родителя и закрывающую скобку:

TMyClass = class(TObject)

Объявления областей видимости начинаются с двух пробелов и, следовательно, области видимости располагаются на одном уровне с идентификатором класса:


  TMyClass = class(TObject)
  private
  protected
  public
  published
  end;

Данные всегда должны располагаться только в приватной секции и названия переменных должны всегда начинаться с префикса F. Все объявления внутри класса должны начинаться с четырех пробелов от крайней левой границы файла:


  TMyClass = class(TObject)
  private
    FMyData: Integer;
    function GetData: Integer;
    procedure SetData(Value: Integer);
  public
  published
    property MyData: Integer read GetData write SetData;
  end;

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

1.11. СТРУКТУРНЫЕ СОСТАВЛЯЮЩИЕ МОДУЛЕЙ И РАЗДЕЛЕНИЕ АЛГОРИТМОВ

Обычно, содержимое каждого созданного модуля есть набор классов, функций и процедур, принадлежащих к одной категории. Например, uХХХLogin содержит все, что относится к идентификации и персонификации пользователя. Для ясного восприятия исходного кода следует придерживаться следующего правила: в интерфейсной части модуля каждая группа функций, относящихся к одной субкатегории должны отделяться от другой группы функций тремя строками с описанием субкатегории на второй строке:

1 
2// Информация о последней попытке идентификации
3 
4procedure GetLastUserName(var ZUser: string);
5procedure GetLastDatabase(var ZDatabase: string);

В секции реализации каждая функционально значимая подкатегория или класс должен разделяться строкой, состоящей из символов звездочки (*), закомментированных однострочным комментарием и пустой строкой перед и после группы функций:


//************************************************************

procedure GetLastUserName(var ZUser: string);
begin
...
end;
procedure GetLastDatabase(var ZDatabase: string);
begin
...
end;

//************************************************************

1.12. ОБЪЯВЛЕНИЕ ПАРАМЕТРОВ

Когда объявляется список параметров для процедуры, функции или метода пользуйтесь следующими рекомендациями:

1.13. ИНИЦИАЛИЗАЦИЯ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ

Глобальные переменные, как и члены класса всегда инициализируются нулем. Это трудно для понимания в случае разных типов. Например Integer инициализируется в 0, а pointer в nil. Для этого рекомендуется указывать в комментарии как инициализируется переменная.


var
  MyGlobalVariable: Pointer // = nil;

Несмотря на то, что глобальные переменные разрешены языком Delphi, используйте их лишь в самых крайних случаях.

1.14. КОЛЛИЗИИ, СВЯЗАННЫЕ С ИМЕНАМИ

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


SysUtils.FindClose(SR);
или
Windows.FindClose(Handle);

1.15. ФОРМЫ, СОЗДАВАЕМЫЕ АВТОМАТИЧЕСКИ

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

1.16. ФУНКЦИИ РЕАЛИЗАЦИИ МОДАЛЬНЫХ ФОРМ

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

Переменная формы должна быть удалена из модуля и объявлена локально в функции реализации формы. Обратите внимание на то, что при этом придется удалить форму из списка автоматического создания в диалоговом окне Project Options.

Приведенный ниже пример иллюстрирует создание подобной функции для формы UserDataForm.


unit UserDataForm; 

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type 
  TUserDataForm = class(TForm)
    edtUserName: TEdit;
    edtUserID: TEdit; 
  private
    { Закрытые объявления } 
  public
    { Открытые объявления } 
  end;

function GetUserData(var aUserName: String; var aUserID: Integer): Word;

implementation

{$R.DFM}

function GetUserData(var aUserName: String; var aUserID: integer): Word; 
var
  UserDataForm: TUserDataForm;
begin
  UserDataForm := TUserDataForm.Create(Application);
  try
    UserDataForm.Caption := 'Получение данных от пользователя';
    Result := UserBataForm.ShOwModal;
    if Result = mrOK then 
    begin       
      aUserName := UserDataForm.edtUserName.Text;
      aUserlD   := StrToInt(UserDataForm.€dtUserIB.Text);     
    end;
  finally
    UserDataForm.Free;   
  end; 
end;

end.

 

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

СОДЕРЖАНИЕ

Copyright © 2004 Вячеслав Колдовский   Специально для Delphi Plus