четверг, 26 августа 2010 г.

Допустимая публичность

В C++ традиционным считается использование public методов в начале описания. И сразу слайды:
class foo {
public:
        foo();
        void doSomething();
private:
        ...
};
И это логично. При чтении кода первое, что мы видим, это доступные нам рычаги для воздействия на класс, его интерфейс. Для тех, кто дочитал до private, становятся известны некоторые подробности реализации. Но речь не о том...

В java объявлений, как таковых нету. В нем объявление и реализация существуют неразрывно. И там принято переменные описывать в начале класса.

В принципе, что в c++, что в java, нет никаких ограничений на порядок следования описаний в классе. Но то, что принято в java - выглядит логично. После описания переменных следуют реализации, которые эти переменные используют.

В том же C++ никто не отменял предварительные описания классов, отдельных функций и переменных. Именно поэтому код выглядит странно:
class bad {
public:
        void action() {
                badness = 100;
        }
        ...
Мы сразу пытаемся найти эту переменную выше по коду. Не пытайтесь найти ее там, это невозможно. Эта переменная находится на несколько сотен строк ниже, перед закрывающей класс скобкой. Мозг протестует, но в c++ это допустимо.

Я вообще с некоторых пор перестал пользоваться инлайн объявлениями, за исключением темплейтов.

Некоторые утверждают, - что дескать инлайн объявления инлайнятся, что делает программу быстрее. А вы уверены? Утверждения о скорости работы необходимо подтверждать цифрами. 80% преждевременной оптимизации лишне. Стоило ли ради этого мнимого ускорения жертвовать удобочитаемостью программы? Ведь освобождая интерфейс класса от ненужных подробностей мы облегчаем его понимание и использование.

Кроме того если возникнет необходимость отладки - лично мне мешаются инлайн функции. Я бы предпочел чтобы каждая функция в исходном тексте оставалась такой же отдельной и в исполняемом модуле. Чтобы по одному содержимому стека проблема прояснялась. Но gcc последнее время стал слишком умным. даже при -O0 -ggdb3 он все равно инлайнит почем зря.

Кроме того, даже самые маленькие методы, такие как int getX() const { return x; } со временем могут подрасти. Что приводит к классам на 500 строк описания, но почему то без cpp файла.

Поэтому я почти всю реализацию описываю отдельно от описания класса. Пусть описание будет чистым. И содержит только то, что невозможно убрать.

Но если, не смотря на все мои уговоры, вам очень хочется описать реализацию в инклюде - следуйте соглашению java и хотя бы переменные описывайте до того, как они будут использованы в коде. Это логично и читатели кода будут вам за это благодарны.