@gth-other

Является ли хорошим решением разбивать большой класс на несколько .cpp файлов (C++)?

Допустим у меня есть класс Example. Его заголовок объявлен в файле Example.hpp. Но если я создам файл Example.cpp (как это обычно делается) и напишу в нем реализацию всех функций, объявленных в файле Example.hpp, то получившийся файл может разрастись на несколько тысяч строк, а это не особо читабельно.

Является ли хорошим решением что-то подобное?
Пример

Example.hpp - заголовок класса
Task1.cpp - реализация функций класса, посвященных задаче Task1
Task2.cpp - реализация функций класса, посвященных задаче Task2
Task3.cpp - реализация функций класса, посвященных задаче Task3
Task4.cpp - реализация функций класса, посвященных задаче Task4
.
.
.
.
  • Вопрос задан
  • 635 просмотров
Решения вопроса 3
Adamos
@Adamos
До появления IDE это могло считаться решением.
Сейчас - никому не нужный и даже мешающий костыль.

Собственно, класс на тысячи строк - сам по себе не проблема.
А вот то, что его хочется раскидать по пяти файлам - явный намек на то, что для упрощения кода требуется рефакторинг.
Ответ написан
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Это очень плохая идея. Теперь пользователю придется искать функцию в 5 файлах, потому что она может быть в любом из них. Если же куски класса можно как-то логически сгруппировать, то надо разбить сам класс на несколько более мелких. Вынести часть функционала в вспомогательные классы или даже тупо функции.

Большой файл - гораздо менее вредно, чем нелогичная файловая структура проекта. Вот большие функции и класс с излишне большой ответственностью - это плохо. А файл - фигня. Строк от разбивки меньше не становится. Ну придется еще переключатся между файлами - только хуже станет.
Ответ написан
Комментировать
@MarkusD Куратор тега C++
все время мелю чепуху :)
Если дать короткий ответ, то всегда следует задуматься о декомпозиции класса в такой ситуации.

Подобный твоему класс представляет из себя монолит - довольно распространенный примитив проектирования, попутно именуемый как "God Object". Объект, который может всё и от которого все вокруг зависят.
Если появляется желание разбить реализацию интерфейса класса на несколько файлов, значит уже есть понимание того, как тематически декомпозировать этот класс и, вероятно, проблема остается только в том, чтобы правильно декомпозировать состояние класса.

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

Если говорить развернуто.

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

В таких случаях люди и приходят к тому, чтобы провести тематическое разделение интерфейса класса и его реализаций. Интерфейс класса делится на тематические секции внутри своих областей доступа. В это же время, каждой тематической секции интерфейса соответствует свой файл исходного кода класса.

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

Общий шаблон такого разделения выглядит так. Чаще всего разработчики именуют файлы именем класса. Например MyClass.h и MyClass.cpp. Когда нужно тематически разделить определение интерфейса, к имени класса после точки и перед расширением файла добавляется суффикс, говорящий о тематике определения. Например MyClass.serialization.cpp, MyClass.crud.cpp или MyClass.callbacks.cpp.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы