0

О хорошем коде.

Сегодня к вечеру меня накрыл приступ графомании. И писать вроде хочется, и в то же время, особо не о чем: дом-работа-дом-работа-дом-работа-дача.... :)

Давно, лет 10 назад, на одном форуме, я увидел тему "Как не надо писать код". В противоположность ей я открыл тему "Как надо писать код". Через пару дней в первой теме было несколько страниц сообщений, а в моей - добавилось только одно или 2. После того случая я не раз замечал, что советов "как не надо" - очень много, а вот "как надо" - днем с огнем не сыщешь. Не пойму - это скромность или страх ответственности за свои слова? Полагаю, что второе, поскольку я еще не встречал программера, который бы публично признал себя.... ну пусть не тупым, но , скажем так, тугодумом :)

Посему я решил взять на себя ответственность сказать, каким должен быть хороший код и как его получить.

Признаки хорошего кода:
1. Хороший код не пребывает долго в неизменном состоянии, потому что он меняется. Именно из-за этого он и хорош - его легко менять, и если вдруг в программу нужно внести изменения, то (если есть такая возможность) проще их сделать в том месте, где их сделать проще :). Иначе говоря, хороший код - код, который легко дополнять и изменять в случае необходимости.
2. Вытекает из первого - хороший код понятен. Именно поэтому его менять легко, - не боишься чего-то поломать. Если не понимаешь, что и для чего делает код, но вносить изменения необходимо - ощущение такое, что движешься по минному полю. Такой код ужасен.

Ну вот пожалуй, и все признаки, остальное - вторично.

Теперь несколько конкретных приемов, облегчающих жизнь. Приемы применимы к объектно-ориентированным языкам с Си-подобным синтаксисом: C++, C#, Java.

1. Старайтесь в качестве параметра метода передавать интерфейс, а возвращать конкретный тип.
Вот это:
ArrayList foo(Map par);
в большинстве случаев лучше, чем вот это:
List foo(HashMap par);
Лучше по той причине, что наверняка избавит вас от необходимости явного приведения типов от базового к производному.
За исключением тех случаев, где метод может возвращать разные типы, производные от одного базового. Тут, естественно, нужно возвращать интерфейс или базовый класс.

2. Любая сущность должна быть тем, чем она выглядит, а не чем-то другим. Т.е. как минимум, переменную, по смыслу являющейся счетчиком, не стоит называть date или gender (нужно назвать counter), а переменную для хранения даты - не стоит называть counter (нужно назвать date).

3. Вместо синглтонов используйте static. Это в продолжение приема №2. В чем разница между синглтоном и static-классом (в C++ это может быть класс с приватным конструктором и исключительно static-полями и методами)? Имхо, только в том, что static-класс сразу показывает, что он есть на самом деле, в то время как синглтон притворяется обычным классом. Единственное исключение, которое мне приходит в голову, - это случай, когда экземпляр класса должен быть единственным, и при этом он обязан реализовать какой-то интерфейс (к примеру, экземпляр этого класса нужно передать в метод, принимающий экземпляры, реализующие этот интерфейс).

4. Не старайтесь делать "задел на будущее". Реализуйте только тот функционал, который необходим для решения заданной задачи, и ни в коем случае не больше. В моей практике еще не было случая, когда сделанный "про запас" функционал пригодился бы в будущем. В лучшем случае он безболезненно удалялся, в худшем - становился рудиментом, мешающим дальнейшему развитию проекта.

5. Ну и конечно, метод должен выполнять такие действия, которые можно сформулировать естественным языком. Написание метода лучше сразу начать с шапки-комментария, в котором будет описано, что метод делает, какие параметры принимает, и для чего они нужны. Если долго не получается написать такое описание, значит или метод должен быть не один. Очень способствует появлению у кода признака №1 :)

6. Вытекает из 5: методы должны быть короткими. Насколько? Должны целиком помещаться на экране. Аналогично 5 очень способствует появлению у кода признака №1 :)

7. Совет насчет классов: если есть трудности в понимании того, какие у класса должны быть методы и какие поля - нужно написать словесное описание того, что класс должен делать. После того, как написали - прочитайте написанное. Глаголы будут означать методы, необходимые классу, существительные - поля класса. Изредка существительные - это параметры, передаваемые в методы.

Все, графоманский зуд удовлетворен:) Можно идти спать :)