Видел очень, очень много кода, которые преподаватели дают студентам для написания программ в ведущих университетах мира - от США до Японии (не шучу).
Кстати, что интересно, во многих случаях к каждому заданию прикреплен файлик про стиль написания и даже что в кампусе приставать ни кому нельзя.
Это к чему: знаю про что говорю.
Мне все равно, с каким Style guide работать, перехожу на него свободно, но порассуждаю, на то она и говорилка. (Вру, не совсем все равно, но частый переход между разными исходниками делают тебя менее чувствительным). Может показаться диким - но смотря какие приоритеты: вальяжно лазить по коду или у тебя времени несколько часов для решения задачи.
Не важно ли это? Да ещё как важно, когда код воспринимается на лету и ты свой взгляд не останавливаешь на ненужных тебе вещах.
Вопрос про префикс get: чтобы уменьшить объем рассуждений. name() или get_name() (getName) пропускаю.
Первый вариант красивее, второй однозначнее.
Вообще, не зависимо от языка программирования, все знают, первая сложность - это дать имена.
И так, стиль Qt
class Object
{
public:
string name()
void setName(...)
private:
string m_name;
}
Сразу невосприятие: С какого перепугу для внутреннего представления идет разделение по подчеркиванию, для внешнего - по заглавным буквам.
Если уж так, называйте тогда mName.
class Object
{
public:
string name( return this->name;)
void setName(...)
private:
string name;
}
Тут вообще путница полная (обратить внимание на this). Я называю (для себя) стилем PHP.
Очень легко ошибиться. Но даже не в ошибке дело. unit тесты все исправят.
Вынос мозга, при написании кода, когда name может быть стековый или принадлежать классу. Задержки не большие, но если в функции много таких переменных зависание обеспечено.
class Object
{
public:
string name( return _name;)
void set_name(...)
private:
string _name;
}
Отлично - приемлемый вариант.
class Object
{
public:
string name( return m_name;)
void set_name(...)
private:
string m_name;
}
Зачем лишний m (m_name)? См. выше.
Область видимости:
class Object
{
string m_name;
public:
string name( return m_name;)
void set_name(...)
}
Тут самое сложное. Многие этим грешат. А что не так?
Для меня не так следующее: Важность данных должна быть сверху вниз. Приватные данные менее важны чем публичные.
Для меня класс выглядит так:
class Object
{
//приватные данные, которые должны бросаться в глаза
friend class ..... -
using type = sometype
public:
using type = sometype //публичный тип
string name( return m_name;)
void setName(...)
private:
приватные функции
private:
приватные переменные.
}
Блоки: тут сложно.
Скобки с новой строки, восприятие однозначное
Сколько раз пробывал:
не идет. Аргументировать не могу.
Лаконично, но играет злую шутку, если вы иногда используете другой вариант
В чем загвоздка - если из одного стиля вы переходите на другой, при дебаге вы можете сделать так:
Вот отгребаешь, когда автоматом закоментил......
Ошибки == и = (перечитались Маерса)
Типа должно быть:
enum E {
V1,
V2,
....
}
if (V1 == value) {
}
В чем смысл, V1 - константа. Мы не можем ошибиться с "==" и "=", т.к. с левой стороны константа.
Это в теории. Если вы ошиблись, беда вам без статического анализатора и/или юнит тестов.
Но такой код не воспринимается.
На практике, такой код гораздо более читаем:
Я не знаю почему, спросите у других почему так, у меня нет объяснений, все так привыкли пИсать (я тоже) и делаю визуальную задержку на другой конструкции.
Усложнение функций с помощью if
Это болезнь всех. В том числе кода, который не должен вызывать сомнения.
Можете взглянуть на любой уважающий для вас код.
int someFunction (p1, p2 .....)
{
if (p1 == nullptr) {
return -1;
} else {
SomeCode
}
}
Что не так?
Другой вариант.
int someFunction (p1, p2 .....)
{
if (p1 == nullptr)
return -1;
SomeCode
На самом деле, такая конструкция избавляет от многих проблем, не только от читаемости кода.
Вынос примитивных(пограничных) проверок в начало избавит от многих if в дальнейшем.
int someFunction (p1, p2 .....)
{
if (p1 == nullptr)
return -1;
if (size() > 0 && val != 0)
return -1;
SomeCode;
В общем случае, вывод пограничных проверок вверх не только увеличивает читаемость кода, но и иногда (да ладно, 80%) увеличивает производительность.
Может показаться смешным, но увеличение производительности связано с простой вещью: вы избавляете себя от лишних условий для кода в дальнейшем. А самые умные из нас не больше 6-7 объектов могут хранить
auto
Использование по Маерсу приводит к проблемам.
Общий случай - только для шаблонов.
Что значит для шаблонов?
auto it = std::find
При использовании auto i = size() приводит к полному невосприятию кода.
Если мы задницей понимаем, что i - это разновидность int, то более сложные случаи ужасны.
Qt не совместим с std по интам. Что мы используем std::vector или QList?
static_cast в коде ужасен повсеместно, но покрайней меры мы должны видеть на уровене кода, что мы получаем
std::size_t или int
И, други мои, это не руководство к действию, это мои никому не нужные размышления.