[[:главная|Главная страница]] ====== Соглашения по исходному коду ====== ===== Именование файлов ===== В именах юнитов с исходным кодом приняты следующие префиксы: * **c_** Юниты в которых объявлены только константы * **t_** Юниты в которых объявлены только простые типы (Record, Enum и тд) * **i_** Юниты в которых объявлены только интерфейсы * **fr_** Юниты в которых объявлены фреймы (Наследники TFrame) * **frm_** Юниты в которых объявлены визуальные формы * **u_** Все остальные юниты, не подходящие под предыдущие префиксы ===== Связи между юнитами ===== * **c_** Юниты могут зависеть только от **t_** Юнитов * **t_** Юниты должны зависеть только от других **t_** Юнитов * **i_** Юниты могут зависеть от **t_** Юнитов и других **i_** Юнитов, циклические связи невозможны в принципе, так как раздел реализации пустой. Все остальные юниты могут зависеть друг от друга, но крайне желательно, что бы в разделе интерфейса были в основном **i_** Юниты и **t_** Юниты. Циклические ссылки между юнитами теоретически возможны, но их нужно максимально избегать. ===== Допустимые типы переменных в API плагинов ===== * **Строки** - //WideString// (//WSTR//). //PWideChar// - допускается, но не рекомендуются. //PAnsiChar// допустим только для ASCII-строк. //PChar// и //ANSI-строки// запрещены. * **Символьные** - //AnsiChar// и //WideChar//. //Char// - запрещено; * **Целые** - //Integer//, //Cardinal//, //Int64//, //UInt64//, //NativeInt//, //NativeUInt//, //Byte//, //Word//. Запрещено использовать //Currency//. * **Вещественные** - //Single// и //Double//. Запрещено использовать //Extended//, //Real//, //Real48// и //Comp//. * **Логический** - //BOOL//. Допускается //ByteBool//, //WordBool// и //LongBool//, но не рекомендуется. //Boolean// - запрещено. * **Статические массивы** - //array[число..число] of// из допустимых типов. * **Записи** - (//record//) из допустимых типов. * **Указатели** - на данные допустимого типа; нетипизированные указатели. * **Интерфейсы** - (//interface//), в методах которых используются допустимые типы. * Запрещено передавать объекты (//TObject//) и компоненты (//TForm//, //TButton//). ====== Форматирование кода ====== ===== Длина строки. ===== Мы предпочитаем делать строки короткими и наглядными. Короткие строки не только более читабельны, но и позволяют задавать операторы в более простой форме (особенно, когда они используются с описательными именами переменных). Методы, состоящие из серий коротких простых операторов, легче для восприятия и модифицирования. Даже диффы в результате точнее показывают, что поменялось между коммитами. ===== Блоки Uses ===== Название каждого юнита с новой строки (опять же для упрощения диффов) примерно в таком порядке: * Системные юниты (SysUtils, Types и тд.) * Юниты библиотек (GR32, KAZip и тд.) * Юниты программы: * Юниты в которых объявлены только константы * Юниты в которых объявлены только простые типы * Юниты в которых объявлены только интерфейсы * Обычные юниты с кодом * Юниты в которых объявлены фреймы * Юниты в которых объявлены визуальные формы ===== Идентификаторы ===== В именах типов, классов, методов, переменных, параметров и тд. Нужно использовать CamelCase. Сразу за именем переменной должно стоять двоеточие, потом пробел, потом имя типа. Пример: VOperationID: Integer; Желательно использовать префиксы: * **T** Имя класса * **I** Имя интерфейса * **V** Локальная переменная функции (Без префикса можно использовать простые счетчики: i, j и тд. но желательно не увлекаться) * **F** Поле класса * **A** Параметр функции * **C** Константа Объявление полей класса только по одному на строку с указанием типа для каждого. Объявление локальных переменных - в большинстве случаев по одному на строку типа для каждой переменной отдельно (исключение простые счетчики) Объявление параметров функций и процедур - по возможности указывать тип для каждой переменной отдельно, если параметров больше чем один-два, то каждый параметр должен расположен на отдельной строке. Пример кода: function FindItems( const AVisualConverter: ILocalCoordConverter; const ALocalPoint: TPoint ): IVectorItemSubset; constructor Create( const ARootFolderName: WideString; const AFolderNameFromRoot: WideString; const AFileMask: WideString; const AFilesOnly: Boolean ); ===== Форматирование кода ===== Необходимо соблюдать отступы. Пробелы перед запятой или точкой с запятой недопустимы. После запятой должен быть пробел. Операторные скобки begin/end обязательны. begin располагается на той же строчке, что и операция к которой он относится. end располагается на новой строчке с тем же отступом, что и команда к которой он относится Пример кода: if FDataRecived then begin VDataRecived := True; FDataRecived := False; end else begin if FLastDataReceiveTick > 0 then begin if FLastDataReceiveTick > VCurrTick then begin FLastDataReceiveTick := VCurrTick; end else begin VTickDelta := VCurrTick - FLastDataReceiveTick; if VTickDelta > VNotDataTimeout then begin FGPSRecorder.AddEmptyPoint; FGpsTrackRecorder.AddEmptyPoint; VDataRecived := True; end; end; end; end; Закомментированный код зло и должен быть удален до коммита. ===== Общие идеи ===== Весь функционал максимально прячется за интерфейсами. Это дает такие преимущества: * Управление временем жизни объектов при помощи автоматического подсчета ссылок. * Интерфейсы можно передавать между границами DLL (Например в плагины и из плагинов), а обычные делфовские объекты нельзя. Пока далеко не все классы имеют интерфейсы и это тормозит появление плагинов. * Имея интерфейс, мы можем делать его реализации совсем не связанными между собой. В интерфейсах нельзя использовать делфовских классов. То есть, если нам нужно возвратить или получить просто бинарные данные, то нужно использовать не TStream, а интерфейс IBinaryData (Сейчас есть пару исключений самое главное TCustomBitmap32, но это временно). Это же касается делфовских динамических массивов, объявленных как //array of// По возможности в интерфейсах нужно избегать использования указателей. Использовать их стоит только если это действительно оправдано.