Именование чистых интерфейсов
От: Videoman Россия https://hts.tv/
Дата: 04.05.23 06:44
Оценка: :)
На всякий случай, используемая терминология:
PascalCase
cammelCase
snake_case

В свете переписывания библиотечного кода на кроссплатформу, принято решения использовать snake_case, как у стандартной библиотеки С++. С этим проблем нет. На 99,9% код использует шаблоны и статический полиморфизм. От сюда duck typing и никаких приседаний с именованием не требуется. Но в некоторых местах всё же необходима динамический полиморфизм и там присутствуют интерфейсы типа IBase и т.д.
Хотел коллег спросить, кто как именует чистые интерфейсные классы, в случае если везде используется snake_case ?

Какие вижу варианты:
// именование интерфейсов
struct ibase;  // [1]
struct i_base; // [2]

// именование файлов
ibase.h        // [1]
i_base.h       // [2]

Первый случай — не очевидно, что это файл интерфейса или класс интерфейса.
Второй случай — не привычно.

Еще есть какие-нибудь варианты?
Отредактировано 04.05.2023 7:00 Videoman . Предыдущая версия .
Re: Именование чистых интерфейсов
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 04.05.23 06:57
Оценка: 1 (1) +3
Здравствуйте, Videoman, Вы писали:

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

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, например
Маньяк Робокряк колесит по городу
Re: Именование чистых интерфейсов
От: so5team https://stiffstream.com
Дата: 04.05.23 07:20
Оценка: 2 (1) +2
Здравствуйте, 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_ раньше был самым корнем иерархии, но со временем он сам стал производен от каких-то дополнительных классов.
Re[2]: Именование чистых интерфейсов
От: night beast СССР  
Дата: 04.05.23 08:28
Оценка: -1
Здравствуйте, so5team, Вы писали:

S>Но вообще жизненный опыт показывает, что в каком-то специальном именовании абстрактных классов смысла нет. Т.к. вначале кажется что abstract_ или _iface в названии как-то помогают, а через N лет оказывается, что то, что было чистым _iface со временем обросло и какими-то невиртуальными вспомогательными методами. А какой-нибудь abstract_ раньше был самым корнем иерархии, но со временем он сам стал производен от каких-то дополнительных классов.


интерфейсы желательно наследовать виртуально, поэтому такой префикс все-же нужен.
Re[3]: Именование чистых интерфейсов
От: so5team https://stiffstream.com
Дата: 04.05.23 08:46
Оценка: +1
Здравствуйте, night beast, Вы писали:

NB>интерфейсы желательно наследовать виртуально


Никогда так не делал, и даже сходу не припомню случая, когда это было бы нужно.

Но, наверное, если без сурового множественного наследования никуда, то такое правило может иметь право на жизнь.
Re[4]: Именование чистых интерфейсов
От: night beast СССР  
Дата: 04.05.23 08:51
Оценка:
Здравствуйте, so5team, Вы писали:

NB>>интерфейсы желательно наследовать виртуально


S>Никогда так не делал, и даже сходу не припомню случая, когда это было бы нужно.

S>Но, наверное, если без сурового множественного наследования никуда, то такое правило может иметь право на жизнь.

проектирование на интерфейсах как раз предполагает суровое множественное наследование.
а поскольку у интерфейсов часто бывает общая база, вот и выходит что без него никуда.
Re[5]: Именование чистых интерфейсов
От: so5team https://stiffstream.com
Дата: 04.05.23 08:53
Оценка:
Здравствуйте, night beast, Вы писали:

NB>а поскольку у интерфейсов часто бывает общая база


Вот с такими вещами практически не сталкивался. Разве что по молодости и сейчас уже не вспомню.
Re[6]: Именование чистых интерфейсов
От: night beast СССР  
Дата: 04.05.23 08:59
Оценка:
Здравствуйте, so5team, Вы писали:

NB>>а поскольку у интерфейсов часто бывает общая база


S>Вот с такими вещами практически не сталкивался. Разве что по молодости и сейчас уже не вспомню.


например тот же IRefCountedBase -- типа у нас все объекты с подсчетом ссылок, чтобы можно было свободно использовать ref_ptr<ISome>.
еще какие-нибудь общие вещи может захотеться по типу комовского IUnknown.
Re[7]: Именование чистых интерфейсов
От: so5team https://stiffstream.com
Дата: 04.05.23 09:03
Оценка:
Здравствуйте, night beast, Вы писали:

S>>Вот с такими вещами практически не сталкивался. Разве что по молодости и сейчас уже не вспомню.


NB>например тот же IRefCountedBase -- типа у нас все объекты с подсчетом ссылок, чтобы можно было свободно использовать ref_ptr<ISome>.


Сценарий понятен, но для моей практики очень уж экзотичен.
Re: Именование чистых интерфейсов
От: fk0 Россия https://fk0.name
Дата: 04.05.23 09:35
Оценка:
Здравствуйте, Videoman, Вы писали:


V>В свете переписывания библиотечного кода на кроссплатформу, принято решения использовать snake_case,


Использовать для чего? Следует разделять именование типов и именование существующих в рантайме сущностей:
объектов, переменных функций.

На мой взгляд для первого (типов) можно использовать CamelCase и snake_case для второго (функций, объектов).
И camelCase для объектов и CamelCase для типов. Смысл в том, что удобно видеть где тип, а где объект/функция.

V>Еще есть какие-нибудь варианты?


Оставить CamelCase для типов, не заниматься идиотскими переименовываниями и не сношать мозг.
Re[3]: Именование чистых интерфейсов
От: Videoman Россия https://hts.tv/
Дата: 04.05.23 12:54
Оценка:
Здравствуйте, night beast, Вы писали:

NB>интерфейсы желательно наследовать виртуально, поэтому такой префикс все-же нужен.

Не-не-не! Я ни за что не агитирую, каждый пусть делает как хочет, но в свое время я наелся с виртуальным наследование — во !!! У меня правило-ограничение, никогда не наследовать множественно реализацию. Только абстрактные интерфейсы, без реализации, и только агрегирование. Типа как в COM, где за 10 лет никогда не использовал никакого виртуального наследования и не жаловался.
Re[4]: Именование чистых интерфейсов
От: night beast СССР  
Дата: 04.05.23 13:02
Оценка:
Здравствуйте, Videoman, Вы писали:

NB>>интерфейсы желательно наследовать виртуально, поэтому такой префикс все-же нужен.

V>Не-не-не! Я ни за что не агитирую, каждый пусть делает как хочет, но в свое время я наелся с виртуальным наследование — во !!! У меня правило-ограничение, никогда не наследовать множественно реализацию. Только абстрактные интерфейсы, без реализации, и только агрегирование. Типа как в COM, где за 10 лет никогда не использовал никакого виртуального наследования и не жаловался.

так даимонд проблема не связана с тем, абстрактный интерфейс или нет.
у тебя один интерфейс наследует два других с общей базой -- вот уже и конфликт.
Re: Именование чистых интерфейсов
От: DiPaolo Россия  
Дата: 04.05.23 13:02
Оценка: 1 (1) +1
V>Еще есть какие-нибудь варианты?

Я раньше придерживался правила, что суффикс Base в названии класса означает интерфейс. Например, PersonBase, VehicleBase.

Альтернативный вариант начинать с I (IPerson, IVehicle) был еще раньше. Но тогда была популярна венгерская нотация и в целом такое было принято в COM. И в кроссплатформенном мире такое сильно неприятно, да и лично мне визуально не нравится.

В итоге я пришел к тому, что называю классы без всяких префиксов (Person, Vehicle). Т.к. само название класса само по себе должно давать понимание, что это за класс. И второе, пользователю класса должно быть пофигу, абстрактный он, или нет. В крайнем случае, он это поймет из контекста или из документации. Ну и помимо прочего, IDE давно уже с легкостью показывают и иерархию, и метки для абстракных/перегруженнных/наследуемых методов.
Патриот здравого смысла
Re: Именование чистых интерфейсов
От: Alekzander  
Дата: 04.05.23 13:19
Оценка: 1 (1)
Здравствуйте, Videoman, Вы писали:

V>Хотел коллег спросить, кто как именует чистые интерфейсные классы


По-COM'овски (IUnknown).
Re[2]: Именование чистых интерфейсов
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 04.05.23 13:27
Оценка: :)
Здравствуйте, fk0, Вы писали:

fk0> Оставить CamelCase для типов, не заниматься идиотскими переименовываниями и не сношать мозг.



Побуду ещё раз занудой, наверное, подразумевался PascalCase. А то CamelCase и camelCase вместе выглядят странно
Маньяк Робокряк колесит по городу
Re[5]: Именование чистых интерфейсов
От: B0FEE664  
Дата: 04.05.23 14:00
Оценка:
Здравствуйте, night beast, Вы писали:

NB>так даимонд проблема не связана с тем, абстрактный интерфейс или нет.

NB>у тебя один интерфейс наследует два других с общей базой -- вот уже и конфликт.
А в чём конфликт?
И каждый день — без права на ошибку...
Re[5]: Именование чистых интерфейсов
От: Videoman Россия https://hts.tv/
Дата: 04.05.23 14:07
Оценка:
Здравствуйте, night beast, Вы писали:

NB>так даимонд проблема не связана с тем, абстрактный интерфейс или нет.

NB>у тебя один интерфейс наследует два других с общей базой -- вот уже и конфликт.

А мне кажется связана. Виртуальное наследование это же про данные. Нет данных — нет виртуальной базы. Чистым интерфейсам не только виртуальное наследование не нужно, но и таблица виртуальных функций — всё хранится в классе.
Вот, пример:
#include <iostream>
#include <memory>

struct base
{
    virtual void base_method() = 0;
};

struct a_interface : base
{
    virtual void a_method() = 0;
};

struct b_interface : base
{
    virtual void b_method() = 0;
};

struct object : a_interface, b_interface 
{
    void base_method() override 
    {
        std::cout << "base_method" << std::endl;
    }

    void a_method() override 
    {
        std::cout << "a_method" << std::endl;
    }

    void b_method() override 
    {
        std::cout << "b_method" << std::endl;
    }
};

int main() 
{
    object obj;
    obj.base_method();
    obj.a_method();
    obj.b_method();
}

base_method
a_method
b_method

Какая разница через какой интерфейс вызов, если данные всё равно расшарены
Re[6]: Именование чистых интерфейсов
От: night beast СССР  
Дата: 04.05.23 14:16
Оценка:
Здравствуйте, 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); // опаньки
}
Re[2]: Именование чистых интерфейсов
От: Videoman Россия https://hts.tv/
Дата: 04.05.23 14:19
Оценка:
Здравствуйте, DiPaolo, Вы писали:

DP>...


DP>В итоге я пришел к тому, что называю классы без всяких префиксов (Person, Vehicle). Т.к. само название класса само по себе должно давать понимание, что это за класс. И второе, пользователю класса должно быть пофигу, абстрактный он, или нет. В крайнем случае, он это поймет из контекста или из документации. Ну и помимо прочего, IDE давно уже с легкостью показывают и иерархию, и метки для абстракных/перегруженнных/наследуемых методов.


В том-то и проблема, что не хочется конфликтов и головняка как отличить Person от интерфейса с таким же названием. Хочется типа такого:
namespace i
{
  struct person;
} 

class person: public i::person
{
  // ..
};

Что бы не думать.
Re[7]: Именование чистых интерфейсов
От: Videoman Россия https://hts.tv/
Дата: 04.05.23 14:41
Оценка:
Здравствуйте, night beast, Вы писали:

NB>...


Тут да, неоднозначность получается. Тогда действительно можно указать virtual, показав, что мне всё равно что компилятор будет звать:
#include <iostream>
#include <memory>

struct base
{
    virtual void base_method() = 0;
};

struct a_interface : virtual base
{
    virtual void a_method() = 0;
};

struct b_interface : virtual base
{
    virtual void b_method() = 0;
};

struct с_interface : a_interface, b_interface
{
    virtual void c_method() = 0;
};

struct object : с_interface 
{
    void base_method() override 
    {
        std::cout << "base_method" << std::endl;
    }

    void a_method() override 
    {
        std::cout << "a_method" << std::endl;
    }

    void b_method() override 
    {
        std::cout << "b_method" << std::endl;
    }

    void c_method() override 
    {
        std::cout << "c_method" << std::endl;
    }
};

int main() 
{
    object obj;

    auto& c = static_cast<с_interface&>(obj);

    c.base_method();
    c.a_method();
    c.b_method();
    c.c_method();
}

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