1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/mirrors-ethereum-solidity

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
CODING_STYLE.md 18 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 27.11.2024 00:00 2bfa411

0. Форматирование

ЗОЛОТОЕ ПРАВИЛО: Следуйте стилю существующего кода при внесении изменений.

  1. Используйте табуляцию для отступа:
    • позиции табуляции каждые 4 символа (актуально только для длины строки).
    • один уровень отступа -> ровно один байт (то есть символ табуляции) в исходном файле.
  2. Ширина строк:
    • строки должны быть не более 99 символов в ширину, чтобы сделать представления diff читаемыми и уменьшить конфликты слияния.
    • строки комментариев должны быть отформатированы в соответствии с удобством просмотра, но простота предпочтительнее красоты.
  3. Блоки с одним оператором не должны иметь фигурных скобок, если это не требуется для ясности.
  4. Никогда не размещайте тела условий на одной строке с условием.
  5. Пробел между ключевым словом и открывающей скобкой, но не после открывающей скобки или перед конечной скобкой.
  6. Нет пробелов для унарных операторов, -> или ..
  7. Нет пробела перед : но один после него, за исключением тернарного оператора: по одному с обеих сторон.
  8. Добавьте пробелы вокруг всех других операторов.
  9. Фигурные скобки, когда они используются, всегда имеют свои собственные строки и находятся на том же уровне отступа, что и «родительская» область.
  10. Если строки разбиты, список элементов, заключённых в круглые скобки (любого вида) и разделённых разделителем (любого вида), форматируется таким образом, чтобы на каждой строке был ровно один элемент, за которым следовал разделитель, открывающая скобка находилась на первой строке, затем следовала строка разрыва, а закрывающая скобка была на отдельной строке без отступа). См. пример ниже.

Да:

if (a == b[i])
    printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'.
foo->bar(
    someLongVariableName,
    anotherLongVariableName,
    anotherLongVariableName,
    anotherLongVariableName,
    anotherLongVariableName
);
cout <<
    "some very long string that contains completely irrelevant " <<
    "text that talks about this and that and contains the words " <<
    "\"lorem\" and \"ipsum\"" <<
    endl;

Нет:

if( a==b[ i ] ) { printf ("Hello\n"); }
foo->bar(someLongVariableName,
         anotherLongVariableName,
         anotherLongVariableName,
         anotherLongVariableName,
         anotherLongVariableName);
cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl;

Чтобы установить настройки отступов и ширины табуляции единообразно, репозиторий содержит файл EditorConfig .editorconfig, который описывает некоторые используемые стили и распознаётся многими IDE и редакторами.

1. Пространства имён

  1. В заголовочных файлах нет объявлений using namespace.
  2. using namespace solidity; и другие пространства имён проекта допустимы в файлах cpp и обычно поощряются.
  3. Избегайте использования using namespace на уровне файла для сторонних библиотек, таких как boost, ranges и т. д.
  4. Все символы должны быть объявлены в пространстве имён, кроме конечных приложений.
  5. Для помощников, область действия которых ограничена файлом cpp, используйте анонимные пространства имён.
  6. Символы препроцессора должны начинаться с имени пространства имён заглавными буквами и подчёркиванием.

Только в заголовке:

#include <cassert>
namespace myNamespace
{
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
}

2. Препроцессор

  1. Файл комментария всегда находится вверху и включает:
    • Авторские права
    • Лицензию (например, см. COPYING)
  2. Никогда не используйте #ifdef/#define/#endif для защиты файлов. Предпочитайте #pragma once в качестве первой строки под комментарием файла.
  3. Предпочитайте статические переменные constexpr макросам значений.
  4. Предпочитайте встроенные функции constexpr функциям-макросам.
  5. Разделите сложный макрос на несколько строк с помощью \.

3. Использование заглавных букв

ЗОЛОТОЕ ПРАВИЛО: Препроцессор: ALL_CAPS; C++: camelCase.

  1. Используйте camelCase для разделения слов в именах, за исключением случаев, когда очевидно расширение функциональности STL/boost, в этом случае следуйте этим соглашениям об именах.
  2. Первая буква следующих сущностей — заглавная:
    • Имена типов
    • Параметры шаблона
    • Члены перечисления
    • статические константные переменные, которые формируют внешний API.
  3. Всё остальное. Символы препроцессора (макросы, аргументы макросов) в полном регистре с разделением слов подчёркиванием.

Все остальные сущности начинаются со строчной буквы.

4. Префиксы переменных

  1. Ведущий знак подчёркивания «_» для параметров функций:
    • Исключение: «o_parameterName», когда он используется исключительно для вывода. См. 6(f).
    • Исключение: «io_parameterName», когда он используется как для ввода, так и для вывода. См. 6(f).
  2. Ведущий «g_» для глобальных (неконстантных) переменных.
  3. Ведущий «s_» для статических (неконстантных, неглобальных) переменных.

5. Утверждения

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

6. Объявления

  1. {Тип} + {квалификаторы} + {имя}.
  2. Только по одному на строку.
  3. Связывайте */& с типом, а не с переменной (на концах с парсером, но более читаемо и безопасно, если в сочетании с (b)).
  4. Предпочитайте объявления рядом с использованием; не объявляйте обычно в начале области видимости, как в C.
  5. Передавайте нетривиальные параметры как константные ссылки, если только данные не должны быть скопированы в функцию, тогда либо передавайте по константной ссылке, либо по значению и используйте std::move.
  6. Если функция возвращает несколько значений, используйте std::tuple (std::pair приемлемо) или лучше введите тип структуры. Не используйте */& аргументы.
  7. Используйте параметры типа указателя, только если nullptr является допустимым аргументом, в противном случае используйте ссылки. Часто std::optional подходит больше, чем необработанный указатель.
  8. Никогда не используйте макрос, где можно написать адекватный код на C++.
  9. Используйте auto только в том случае, если тип очень длинный и не имеет значения.
  10. Не передавайте bool: вместо этого предпочитайте перечисления.
  11. Предпочитайте enum class прямому перечислению.
  12. Всегда инициализируйте POD-переменные, даже если их значение будет перезаписано позже.

Да:

enum class Accuracy
{
    Approximate,
    Exact
};
struct MeanSigma
{
    float mean = 0.0f;
    float standardDeviation = 1.0f;
};
double const d = 0;
int i = 0;
int j = 0;
char* s = nullptr;
MeanAndSigma ms meanAndSigma(std::vector<float> const& _v, Accuracy _a);
Derived* x = dynamic_cast<Derived*>(base);
for (auto i = x->begin(); i != x->end(); ++i) {}

Нет:

const double d = 0;
int i, j;
char *s;
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
Derived* x(dynamic_cast<Derived*>(base));
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}

7. Структуры и классы

  1. Структуры следует использовать, когда все члены являются публичными и нет виртуальных функций:
    • В этом случае члены должны называться естественно и не начинаться с m_.
  2. Классы следует использовать во всех остальных случаях.

8. Члены

  1. По одному члену на строку.
  2. Частные, нестатические, неконстантные поля начинаются с m_.
  3. Избегайте публичных полей, за исключением структур.
  4. Как можно чаще используйте override, final и const.
  5. Нет реализаций с объявлением класса, кроме:
    • шаблонного или принудительно встроенного метода (хотя предпочтительнее реализация в нижней части файла заголовка).
    • однострочной реализации (в этом случае включите её в ту же строку, что и объявление).
  6. Для свойства foo:
    • Член: m_foo
    • Получатель: foo() [также: для логических значений isFoo()]
    • Установщик: setFoo()

9. Именование

  1. Избегайте труднопроизносимых имён.
  2. Имена следует сокращать только в случае крайней распространённости, но в целом следует избегать сокращения.
  3. Избегайте префиксов инициалов (например, не используйте IMyInterface, CMyImplementation).
  4. Найдите короткие, запоминающиеся и (по крайней мере полу-) описательные имена для часто используемых классов или фрагментов имён:
    • Словарь и тезаурус — ваши друзья;
    • Пишите правильно;
    • Тщательно продумайте цель класса;
    • Представьте его как изолированный компонент, чтобы попытаться деконтекстуализировать его при рассмотрении его имени;
    • Не ограничивайтесь именованием его (исключительно) с точки зрения его реализации.

10. Определения типов

  1. Предпочитайте using вместо typedef. Например, using ints = std::vector; вместо typedef std::vector ints; Использование shared_ptr вместо сокращения до ptr

  2. В случае исключений из этого правила (из-за чрезмерного использования и ясного смысла), отметьте изменение заметно и используйте его последовательно:

    • например, using Guard = std::lock_guard<std::mutex>; ///< Guard используется во всей кодовой базе, так как он ясен по смыслу и широко используется.
  3. Как правило, выражения должны быть примерно такими же важными/семантически значимыми, как пространство, которое они занимают.

  4. Избегайте введения псевдонимов для типов, если только они не являются очень сложными. Учитывайте количество элементов, которые мозг может отслеживать одновременно.

11. Комментирование

  1. Комментарии должны быть совместимы с doxygen, используя @нотацию вместо \нотации.
  2. Документируйте интерфейс, а не реализацию:
    • документация должна быть в состоянии остаться полностью неизменной, даже если метод будет перереализован;
    • комментируйте с точки зрения свойств метода и предполагаемого изменения состояния класса (или того, какие аспекты состояния он сообщает);
    • будьте осторожны при анализе документации, которая распространяется только на предполагаемое назначение и использование;
    • отклоняйте документацию, которая является просто переводом реализации на английский язык.
  3. Избегайте комментариев в коде. Вместо этого попробуйте выделить блоки функциональности в функции. Это часто уже устраняет необходимость в комментарии в коде.

12. Включить заголовки

  1. Включаемые файлы должны идти в порядке увеличения общности (libsolidity -> libevmasm -> libsolutil -> boost -> STL).
  2. Соответствующий файл .h должен быть первым включением в соответствующий файл .cpp.
  3. Между блоками включаемых файлов следует вставлять пустые строки.

Пример:

#include <libsolidity/codegen/ExpressionCompiler.h>

#include <libsolidity/ast/AST.h>
#include <libsolidity/codegen/CompilerContext.h>
#include <libsolidity/codegen/CompilerUtils.h>
#include <libsolidity/codegen/LValue.h>

#include <libevmasm/GasMeter.h>

#include <libsolutil/Common.h>
#include <libsolutil/SHA3.h>

#include <boost/range/adaptor/reversed.hpp>
#include <boost/algorithm/string/replace.hpp>

#include <utility>
#include <numeric>

См. эту проблему для объяснения: это облегчает поиск отсутствующих включений в заголовочных файлах.

13. Рекомендуемая литература

  • Херб Саттер и Бьярн Страуструп:

  • Херб Саттер и Андрей Александреску:

    • «Стандарты кодирования C++: 101 правило, руководство и лучшие практики»
  • Скотт Мейерс:

    • «Эффективный C++: 55 конкретных способов улучшить ваши программы и дизайн (3-е издание)»
    • «Более эффективный C++: 35 новых способов улучшить ваши программы и дизайн»
    • «Эффективный современный C++: 42 конкретных способа улучшить ваше использование C++11 и C++14»

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/mirrors-ethereum-solidity.git
git@api.gitlife.ru:oschina-mirror/mirrors-ethereum-solidity.git
oschina-mirror
mirrors-ethereum-solidity
mirrors-ethereum-solidity
develop