В свете переписывания библиотечного кода на кроссплатформу, принято решения использовать snake_case, как у стандартной библиотеки С++. С этим проблем нет. На 99,9% код использует шаблоны и статический полиморфизм. От сюда duck typing и никаких приседаний с именованием не требуется. Но в некоторых местах всё же необходима динамический полиморфизм и там присутствуют интерфейсы типа IBase и т.д.
Хотел коллег спросить, кто как именует чистые интерфейсные классы, в случае если везде используется snake_case ?
По сути вопроса не подскажу, так как всегда используется другая нотация. Просто по мелочи попридираюсь
V>На всякий случай, используемая терминология:
V>sname_case
V>
Я так понимаю, имелся в виду snake_case, а то у тебя везде по тексту какой-то непонятный зверь sname_case
V>В свете переписывания библиотечного кода на кроссплатформу, принято решения использовать sname_case, как у стандартной библиотеки С++. С этим проблем нет. На 99,9% код использует шаблоны и статический полиморфизм. От сюда duck typing и никаких приседаний с именованием не требуется. Но в некоторых местах всё же необходима динамический полиморфизм и там присутствуют интерфейсы типа IBase и т.д. V>Хотел коллег спросить, кто как именует чистые интерфейсные классы, в случае если везде используется sname_case ?
Не использую snake_case, вернее, ограниченно использую в тех частях, которые типа косят под стандартную библиотеку. В остальном коде — PascalCase, функции и мемберы — camelCase. Позволяет визуально разделять C++ сущности, свои сущности, и третьесторонние сущности
V>Первый случай — не очевидно, что это файл интерфейса или класс интерфейса. V>Второй случай — не привычно.
Ничего, привыкнешь
V>Еще есть какие-нибудь варианты?
IPascalCase
Не вижу проблемы в миксе форматирования. Интерфейсы — всегда PascalCase с префиксом I, реализации — snake_case, например
Здравствуйте, Videoman, Вы писали:
V>Хотел коллег спросить, кто как именует чистые интерфейсные классы, в случае если везде используется snake_case ?
Иногда бывает необходимость выделить корень какой-то иерархии классов и тогда хочется, чтобы в названии было что-то, что бы говорило, что это уже корень, отсюда все и растет. В таких случаях название начинается с abstract_, вроде abstract_message_mbox, abstract_message_sink, abstract_connection_pool.
Иногда используется суффикс _iface, вроде notificator_iface, controller_iface, consumer_iface. Правильнее, наверное, было бы использовать _interface, но слишком уж длинные названия получаются. При этом _iface не обязательно означает абстрактный класс, иногда это вполне себе обычный класс, просто дающий какой-то другой способ доступа к объекту. Что-то вроде:
// Публично-доступная часть.namespace impl {
class private_consumer_iface;
}
class consumer {
friend class impl::private_consumer_iface;
...
public:
void a();
void b();
...
};
// Приватная часть, детали реализации.
// Скорее всего, другая единица трансляции.namespace impl {
class private_consumer_iface {
public:
void c(consumer & target);
void d(consumer & target);
...
};
}
Но вообще жизненный опыт показывает, что в каком-то специальном именовании абстрактных классов смысла нет. Т.к. вначале кажется что abstract_ или _iface в названии как-то помогают, а через N лет оказывается, что то, что было чистым _iface со временем обросло и какими-то невиртуальными вспомогательными методами. А какой-нибудь abstract_ раньше был самым корнем иерархии, но со временем он сам стал производен от каких-то дополнительных классов.
Здравствуйте, so5team, Вы писали:
S>Но вообще жизненный опыт показывает, что в каком-то специальном именовании абстрактных классов смысла нет. Т.к. вначале кажется что abstract_ или _iface в названии как-то помогают, а через N лет оказывается, что то, что было чистым _iface со временем обросло и какими-то невиртуальными вспомогательными методами. А какой-нибудь abstract_ раньше был самым корнем иерархии, но со временем он сам стал производен от каких-то дополнительных классов.
интерфейсы желательно наследовать виртуально, поэтому такой префикс все-же нужен.
Здравствуйте, so5team, Вы писали:
NB>>интерфейсы желательно наследовать виртуально
S>Никогда так не делал, и даже сходу не припомню случая, когда это было бы нужно. S>Но, наверное, если без сурового множественного наследования никуда, то такое правило может иметь право на жизнь.
проектирование на интерфейсах как раз предполагает суровое множественное наследование.
а поскольку у интерфейсов часто бывает общая база, вот и выходит что без него никуда.
Здравствуйте, so5team, Вы писали:
NB>>а поскольку у интерфейсов часто бывает общая база
S>Вот с такими вещами практически не сталкивался. Разве что по молодости и сейчас уже не вспомню.
например тот же IRefCountedBase -- типа у нас все объекты с подсчетом ссылок, чтобы можно было свободно использовать ref_ptr<ISome>.
еще какие-нибудь общие вещи может захотеться по типу комовского IUnknown.
Здравствуйте, night beast, Вы писали:
S>>Вот с такими вещами практически не сталкивался. Разве что по молодости и сейчас уже не вспомню.
NB>например тот же IRefCountedBase -- типа у нас все объекты с подсчетом ссылок, чтобы можно было свободно использовать ref_ptr<ISome>.
Сценарий понятен, но для моей практики очень уж экзотичен.
V>В свете переписывания библиотечного кода на кроссплатформу, принято решения использовать snake_case,
Использовать для чего? Следует разделять именование типов и именование существующих в рантайме сущностей:
объектов, переменных функций.
На мой взгляд для первого (типов) можно использовать CamelCase и snake_case для второго (функций, объектов).
И camelCase для объектов и CamelCase для типов. Смысл в том, что удобно видеть где тип, а где объект/функция.
V>Еще есть какие-нибудь варианты?
Оставить CamelCase для типов, не заниматься идиотскими переименовываниями и не сношать мозг.
Здравствуйте, night beast, Вы писали:
NB>интерфейсы желательно наследовать виртуально, поэтому такой префикс все-же нужен.
Не-не-не! Я ни за что не агитирую, каждый пусть делает как хочет, но в свое время я наелся с виртуальным наследование — во !!! У меня правило-ограничение, никогда не наследовать множественно реализацию. Только абстрактные интерфейсы, без реализации, и только агрегирование. Типа как в COM, где за 10 лет никогда не использовал никакого виртуального наследования и не жаловался.
Здравствуйте, Videoman, Вы писали:
NB>>интерфейсы желательно наследовать виртуально, поэтому такой префикс все-же нужен. V>Не-не-не! Я ни за что не агитирую, каждый пусть делает как хочет, но в свое время я наелся с виртуальным наследование — во !!! У меня правило-ограничение, никогда не наследовать множественно реализацию. Только абстрактные интерфейсы, без реализации, и только агрегирование. Типа как в COM, где за 10 лет никогда не использовал никакого виртуального наследования и не жаловался.
так даимонд проблема не связана с тем, абстрактный интерфейс или нет.
у тебя один интерфейс наследует два других с общей базой -- вот уже и конфликт.
Я раньше придерживался правила, что суффикс Base в названии класса означает интерфейс. Например, PersonBase, VehicleBase.
Альтернативный вариант начинать с I (IPerson, IVehicle) был еще раньше. Но тогда была популярна венгерская нотация и в целом такое было принято в COM. И в кроссплатформенном мире такое сильно неприятно, да и лично мне визуально не нравится.
В итоге я пришел к тому, что называю классы без всяких префиксов (Person, Vehicle). Т.к. само название класса само по себе должно давать понимание, что это за класс. И второе, пользователю класса должно быть пофигу, абстрактный он, или нет. В крайнем случае, он это поймет из контекста или из документации. Ну и помимо прочего, IDE давно уже с легкостью показывают и иерархию, и метки для абстракных/перегруженнных/наследуемых методов.
Здравствуйте, night beast, Вы писали:
NB>так даимонд проблема не связана с тем, абстрактный интерфейс или нет. NB>у тебя один интерфейс наследует два других с общей базой -- вот уже и конфликт.
А в чём конфликт?
Здравствуйте, night beast, Вы писали:
NB>так даимонд проблема не связана с тем, абстрактный интерфейс или нет. NB>у тебя один интерфейс наследует два других с общей базой -- вот уже и конфликт.
А мне кажется связана. Виртуальное наследование это же про данные. Нет данных — нет виртуальной базы. Чистым интерфейсам не только виртуальное наследование не нужно, но и таблица виртуальных функций — всё хранится в классе.
Вот, пример:
Здравствуйте, Videoman, Вы писали:
NB>>так даимонд проблема не связана с тем, абстрактный интерфейс или нет. NB>>у тебя один интерфейс наследует два других с общей базой -- вот уже и конфликт.
V>А мне кажется связана. Виртуальное наследование это же про данные. Нет данных — нет виртуальной базы. Чистым интерфейсам не только виртуальное наследование не нужно, но и таблица виртуальных функций — всё хранится в классе.
V>Какая разница через какой интерфейс вызов, если данные всё равно расшарены
ты не работаешь напрямую с объектами, ты работаешь с интерфейсами:
struct IBase {
virtual ~IBase() {}
};
struct IA : IBase {
};
struct IB : IBase {
};
struct IC : IA, IB {
};
int main()
{
IC * c = new IC();
IBase* x = static_cast<IBase*>(c); // опаньки
}
Здравствуйте, DiPaolo, Вы писали:
DP>...
DP>В итоге я пришел к тому, что называю классы без всяких префиксов (Person, Vehicle). Т.к. само название класса само по себе должно давать понимание, что это за класс. И второе, пользователю класса должно быть пофигу, абстрактный он, или нет. В крайнем случае, он это поймет из контекста или из документации. Ну и помимо прочего, IDE давно уже с легкостью показывают и иерархию, и метки для абстракных/перегруженнных/наследуемых методов.
В том-то и проблема, что не хочется конфликтов и головняка как отличить Person от интерфейса с таким же названием. Хочется типа такого:
namespace i
{
struct person;
}
class person: public i::person
{
// ..
};