У меня есть функция User::func() (callback), которая будет вызвана классом шаблона (Library<T>).
На первой итерации развития все знают, что func() служит только для этой единственной цели.
Несколько месяцев спустя большинство членов забывают, что такое func().
После некоторого тяжелого рефакторинга, func() иногда удаляется некоторыми кодировщиками.
Сначала я не думал, что это проблема вообще.
Однако после того, как я несколько раз столкнулся с этим шаблоном, мне кажется, что мне нужна контрмера.
Вопрос
Как оформлять его элегантно? (cute && сжатие && no дополнительные затраты ЦП)
Пример
Вот упрощенный код: -
(Реальная проблема заключается в рассеянии около 10+ библиотечных файлов и 20 + пользовательских файлов и более 40 функций.)
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
node->func(); //#1
}
};
user.h
class User{
public: void func(){/** some code*/} //#1
//... a lot of other functions ...
// some of them are also callback of other libraries
};
main.cpp
int main(){
Library<User> li; .... ; li.utility();
}
Мои плохие решения
1. Комментарий /doc
В качестве первого обходного пути я хотел бы добавить комментарий следующим образом: -
class User{
/** This function is for "Library" callback */
public: void func(){/** some code*/}
};
Но он становится грязным довольно быстро - я должен добавить его к каждому "func" в каждом классе.
2. Переименуйте "func()"
В реальном случае я предпочитаю префикс имени функции следующим образом: -
class User{
public: void LIBRARY_func(){/** some code*/}
};
Это очень заметно, но имя функции теперь очень велико.
(особенно когда Library -класс имеет более длинное имя класса)
3. Виртуальный класс с "func() = 0"
Я рассматриваю возможность создания абстрактного класса в качестве интерфейса для обратного вызова.
class LibraryCallback{
public: virtual void func()=0;
};
class User : public LibraryCallback{
public: virtual void func(){/** some code*/}
};
Он обеспечивает ощущение, что func() для что-то-довольно-внешнего. :)
Тем не менее, я должен пожертвовать стоимостью виртуального вызова (v-table).
В критичных по производительности случаях я не могу себе этого позволить.
4. Статическая функция
(идея от Дэниела Жора в комментарии, спасибо!)
Почти через месяц, вот как я использую: -
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
T::func(node); //#1
}
};
user.h
class User{
public: static void func(Callback*){/** some code*/}
};
main.cpp
int main(){
Library<User> li;
}
Это, вероятно, более чистый, но все еще не хватает самодокумента.