Здесь показаны различия между двумя версиями данной страницы.
|
sasdev:соглашения_по_исходному_коду [02/04/2012 09:47] 194.85.160.130 [Блоки Uses] |
sasdev:соглашения_по_исходному_коду [10/01/2020 16:35] (текущий) 213.91.147.82 [Длина строки.] |
||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| - | ====== Именование файлов ====== | + | [[:главная|Главная страница]] |
| + | |||
| + | ====== Соглашения по исходному коду ====== | ||
| + | |||
| + | ===== Именование файлов ===== | ||
| В именах юнитов с исходным кодом приняты следующие префиксы: | В именах юнитов с исходным кодом приняты следующие префиксы: | ||
| * **c_** Юниты в которых объявлены только константы | * **c_** Юниты в которых объявлены только константы | ||
| Строка 8: | Строка 12: | ||
| * **u_** Все остальные юниты, не подходящие под предыдущие префиксы | * **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 ===== | ===== Блоки Uses ===== | ||
| - | Название каждого юнита с новой строки примерно в таком порядке: | + | Название каждого юнита с новой строки (опять же для упрощения диффов) примерно в таком порядке: |
| * Системные юниты (SysUtils, Types и тд.) | * Системные юниты (SysUtils, Types и тд.) | ||
| * Юниты библиотек (GR32, KAZip и тд.) | * Юниты библиотек (GR32, KAZip и тд.) | ||
| Строка 25: | Строка 48: | ||
| ===== Идентификаторы ===== | ===== Идентификаторы ===== | ||
| В именах типов, классов, методов, переменных, параметров и тд. Нужно использовать CamelCase. | В именах типов, классов, методов, переменных, параметров и тд. Нужно использовать CamelCase. | ||
| + | |||
| Сразу за именем переменной должно стоять двоеточие, потом пробел, потом имя типа. | Сразу за именем переменной должно стоять двоеточие, потом пробел, потом имя типа. | ||
| + | |||
| Пример: | Пример: | ||
| + | |||
| VOperationID: Integer; | VOperationID: Integer; | ||
| Желательно использовать префиксы: | Желательно использовать префиксы: | ||
| + | * **T** Имя класса | ||
| + | * **I** Имя интерфейса | ||
| * **V** Локальная переменная функции (Без префикса можно использовать простые счетчики: i, j и тд. но желательно не увлекаться) | * **V** Локальная переменная функции (Без префикса можно использовать простые счетчики: i, j и тд. но желательно не увлекаться) | ||
| * **F** Поле класса | * **F** Поле класса | ||
| Строка 35: | Строка 63: | ||
| * **C** Константа | * **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// | ||
| + | По возможности в интерфейсах нужно избегать использования указателей. Использовать их стоит только если это действительно оправдано. | ||