SAS.Wiki

Веб-картография и навигация

Инструменты пользователя

Инструменты сайта


sasdev:соглашения_по_исходному_коду

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

sasdev:соглашения_по_исходному_коду [09/06/2011 07:36]
vdemidov создано
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 =====
 +Название каждого юнита с новой строки (опять же для упрощения диффов) примерно в таком порядке:​
 +  * Системные юниты (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//
 +По возможности в интерфейсах нужно избегать использования указателей. Использовать их стоит только если это действительно оправдано.