Выражайте свои намерения в коде явно
Всегда, когда мы пишем код, мы должны помнить одну вещь. То, что мы написали, потом будут читать. Много много раз. Фактически, вы пишите книгу о том, что делается у вас проекте. Безусловно, эта книга не будет понятна 99.9% жителей планеты. Однако иногда такой код пишется, что 99.9% программистов он непонятен)
Есть много разных способов сделать свой код понятнее для коллег. Расскажу про один из таких способов.
Если назначение какого-либо кода не указано (например, в именах переменных или комментариях), трудно сказать, делает ли код то, что должен делать(да и в принципе что этот код делает). Например:
int i = 0;
while (i < v.size()) {
// ... a lot of operations with v[i]...
}
...
Что в этом куске кода не так? Он непонятный. Ну то есть тут все читаемо и мы понимаем механику, как какие-то операции делаются. Но мы не понимаем главного. Намерений. Смысла.
Довольно часто нам приходится разбираться в новом чужом коде. И выражение намерений с помощью языковых конструкций дает огромный буст в понимании происходящего.
Вот возьмем код сверху. Мы понимаем, что есть какой-то цикл и есть переменная i, которая вроде как индекс и вот мы чет-то делаем до тех пор, пока не этот индекс не достигнет размера какого-то объекта. Непонятно, почему индекс объявлен вне цикла. Непонятно, будет ли он использоваться дальше и зачем. А человек всего лишь хотел обойти элементы массива и сделать с ними что-то. Почему бы не написать сразу вот так:
for (const auto& point : points_for_drawing) { DrawPoint(point);}
Это даже читать можно. Для каждой точки из набора точек для рисования нужно отрисовать точку. Причем сразу понятно, что DrawPoint не может изменить точку. Или так:
for (auto& point : points_for_drawing) { ReflectOx(point);}
Для каждой точки из набора точек для рисования нужно отразить ее относительно оси абсцисс. Это потребует изменения точек, поэтому ссылка неконстантная.
Здесь нет акцента на итерировании и способе прохождения по массиву. Я здесь выражаю намерение, а не способ достижения результата. ЧТО я хочу сделать, а не КАК.
Иногда можно использовать именованные алгоритмы для большей ясности повествования.
std::for_each (points_for_drawing.begin(), points_for_drawing.end(), ReflectOx(point));
Вариант не универсальный, но всегда нужно оценивать возможность этого подхода.
Выражайте свои намерения в коде. Это и вам помогает подняться на уровень выше и научиться понятно доносить свои мысли до людей. Ведь мы их доносим для того, чтобы нас поняли. И очень круто, если процесс понимания будет занимать минимум времени.
Stay clear. Stay cool.
#goodpractice
Всегда, когда мы пишем код, мы должны помнить одну вещь. То, что мы написали, потом будут читать. Много много раз. Фактически, вы пишите книгу о том, что делается у вас проекте. Безусловно, эта книга не будет понятна 99.9% жителей планеты. Однако иногда такой код пишется, что 99.9% программистов он непонятен)
Есть много разных способов сделать свой код понятнее для коллег. Расскажу про один из таких способов.
Если назначение какого-либо кода не указано (например, в именах переменных или комментариях), трудно сказать, делает ли код то, что должен делать(да и в принципе что этот код делает). Например:
int i = 0;
while (i < v.size()) {
// ... a lot of operations with v[i]...
}
...
Что в этом куске кода не так? Он непонятный. Ну то есть тут все читаемо и мы понимаем механику, как какие-то операции делаются. Но мы не понимаем главного. Намерений. Смысла.
Довольно часто нам приходится разбираться в новом чужом коде. И выражение намерений с помощью языковых конструкций дает огромный буст в понимании происходящего.
Вот возьмем код сверху. Мы понимаем, что есть какой-то цикл и есть переменная i, которая вроде как индекс и вот мы чет-то делаем до тех пор, пока не этот индекс не достигнет размера какого-то объекта. Непонятно, почему индекс объявлен вне цикла. Непонятно, будет ли он использоваться дальше и зачем. А человек всего лишь хотел обойти элементы массива и сделать с ними что-то. Почему бы не написать сразу вот так:
for (const auto& point : points_for_drawing) { DrawPoint(point);}
Это даже читать можно. Для каждой точки из набора точек для рисования нужно отрисовать точку. Причем сразу понятно, что DrawPoint не может изменить точку. Или так:
for (auto& point : points_for_drawing) { ReflectOx(point);}
Для каждой точки из набора точек для рисования нужно отразить ее относительно оси абсцисс. Это потребует изменения точек, поэтому ссылка неконстантная.
Здесь нет акцента на итерировании и способе прохождения по массиву. Я здесь выражаю намерение, а не способ достижения результата. ЧТО я хочу сделать, а не КАК.
Иногда можно использовать именованные алгоритмы для большей ясности повествования.
std::for_each (points_for_drawing.begin(), points_for_drawing.end(), ReflectOx(point));
Вариант не универсальный, но всегда нужно оценивать возможность этого подхода.
Выражайте свои намерения в коде. Это и вам помогает подняться на уровень выше и научиться понятно доносить свои мысли до людей. Ведь мы их доносим для того, чтобы нас поняли. И очень круто, если процесс понимания будет занимать минимум времени.
Stay clear. Stay cool.
#goodpractice