Плохая практика - иметь несколько классов в одном файле?

82

Раньше у меня был один класс на один файл. Например, car.cs имеет класс car . Но поскольку я программирую больше классов, я хотел бы добавить их в тот же файл. Например car.cs имеет класс автомобиля и дверь класса, и т.д.

Мой вопрос подходит для Java, C #, PHP или любого другого языка программирования. Должен ли я попробовать не иметь несколько классов в одном файле или это нормально?

Покус
источник

Ответы:

94

Я думаю, вам следует попытаться сохранить свой код по одному классу на файл.

Я предлагаю это, потому что позже вам будет легче найти свой класс. Кроме того, он будет лучше работать с вашей системой управления версиями (если файл изменяется, вы знаете, что изменился конкретный класс).

Единственный раз, когда я считаю правильным использовать более одного класса для файла, - это когда вы используете внутренние классы ... но внутренние классы находятся внутри другого класса и, следовательно, могут быть оставлены внутри того же файла. Роли внутренних классов сильно связаны с внешними классами, поэтому их можно разместить в одном файле.

Патрик Дежарден
источник
1
Увидев, что kotlin может делать в одном файле, я начинаю полагать, что некоторые вещи, такие как DTO, могут быть в одном файле.
John Tribe
1
В дополнение к этому, классы, которые у вас будут в одном файле, обычно тесно связаны, что может затруднить редактирование, поскольку не так просто просматривать несколько классов одновременно. Придется много листать. Разделенное представление помогает, но это не так просто, как отдельное окно для каждого файла / класса.
Chad Hedgcock
А как насчет автозагрузки? При определении нескольких классов в одном исходном файле функция автозагрузки станет более сложной. см. stackoverflow.com/questions/37982012/…
Александр Белинг
26

В Java один общедоступный класс для каждого файла - это способ работы языка. Группа файлов Java может быть собрана в пакет.

Однако в Python файлы являются «модулями» и обычно имеют ряд тесно связанных классов. Пакет Python - это каталог, как и пакет Java.

Это дает Python дополнительный уровень группировки между классом и пакетом.

Не существует единственного верного ответа, независимого от языка. Это зависит от языка.

С.Лотт
источник
23

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

public class Customer { /* whatever */ }

public class CustomerCollection : List<Customer> { /* whatever */ }

Лучшее практическое правило - сохранять один класс для каждого файла, кроме тех случаев, когда это начинает усложнять задачу, а не упрощает ее. Поскольку поиск в файлах Visual Studio настолько эффективен, вам, вероятно, в любом случае не придется тратить много времени на просмотр файловой структуры.

Райан Ланди
источник
3
Нет. Это плохой совет. Воспользуйтесь советом принятого ответа. Вы должны отделить репозиторий объектов от сохраняемого класса. Это просто создает ненужную путаницу.
Hudson
4
@Hudson Я не вижу выше кода "репозитория объектов".
Райан Ланди
18

Нет, я не считаю это плохой практикой. Я имею в виду, что в общем лучше иметь отдельный файл для каждого класса, но есть определенные исключения, когда лучше иметь несколько классов в одном файле. Хорошим примером этого является группа классов Exception. Если у вас есть несколько десятков таких классов для данной группы, действительно ли имеет смысл иметь отдельный отдельный файл для каждого двух классов лайнера? Я бы не стал спорить. В этом случае иметь группу исключений в одном классе гораздо менее громоздко и просто ИМХО.

Джеймс
источник
10

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

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

Даниэль Шаффер
источник
9

Поскольку ваша среда IDE предоставляет вам функцию « Перейти к », и у вас есть некоторый контроль над пространством имен в своих классах, то приведенные ниже преимущества наличия нескольких классов в одном файле для меня вполне того стоят.

Родительские - дочерние классы

Во многих случаях я считаю весьма полезным иметь унаследованные классы в своем файле базового класса.

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

Public: Small - Helper - DTO Classes

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

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

В целом нарушение железного правила «1 класс на файл» дает некоторую дополнительную свободу в организации кода.

Что произойдет дальше, на самом деле зависит от вашей IDE, языка, навыков командного общения и организационных навыков.

Но если вы хотите эту свободу, зачем жертвовать ею ради железного правила?

Анестис Кивраноглу
источник
7

Если вы работаете в команде, хранение классов в отдельных файлах упрощает управление источником и снижает вероятность конфликтов (несколько разработчиков одновременно изменяют один и тот же файл). Я думаю, это также упрощает поиск кода, который вы ищете.

Джим Андерсон
источник
7

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

Буджум
источник
6

Это может быть плохо с точки зрения будущего развития и ремонтопригодности. Намного легче запомнить, где находится класс Car, если у вас есть класс Car.cs. Где бы вы искать класс Widget, если Widget.cs не существует? Это автомобильный виджет? Это виджет двигателя? А может это виджет рогалика.

Стивен Бенке
источник
2
Как упоминалось в stackoverflow.com/questions/360643/… , с общими инструментами навигации вам все равно не нужно перемещаться по файлу. Вместо этого вы перемещаетесь по классам / членам.
Suma
6

Только раз , когда я считаю расположение файлов, когда я должен создать новые классы. В противном случае я никогда не использую файловую структуру. Я использую «перейти к классу» или «перейти к определению».

Я знаю, что это в некоторой степени проблема обучения; Освобождение себя от физической файловой структуры проектов требует практики. Хотя это очень полезно;)

Если вы хотите поместить их в один файл, будь моим гостем. Не могу сделать это с общедоступными классами в java;)

Кросенвольд
источник
2

Как правило, лучше всего использовать один класс / один файл. Однако я часто храню несколько определений интерфейсов в одном файле. Несколько классов в одном файле? Только если они как-то очень тесно связаны и очень маленькие (<5 методов и членов)

Треб
источник
2

Как и в большинстве случаев в программировании, это сильно зависит от ситуации.

Например, какова сплоченность рассматриваемых классов? Они сильно связаны? Они полностью ортогональны? Связаны ли они по функциональности?

Для веб-фреймворка было бы нормальным предоставлять виджеты общего назначения, какой бы файл ни содержал BaseWidget, TextWidget, CharWidget и т. Д.

Пользователь фреймворка не нарушит правила, если определит файл more_widgets, содержащий дополнительные виджеты, которые они выводят из виджетов фреймворка для своего конкретного доменного пространства.

Когда классы ортогональны и не имеют ничего общего друг с другом, группировка в один файл действительно будет искусственной. Предположим, что приложение управляет роботизированной фабрикой, производящей автомобили. Файл с именем parts, содержащий CarParts и RobotParts, был бы бессмысленным ... вряд ли существует большая связь между заказом запасных частей для обслуживания и деталями, которые производит завод. Такое объединение не добавит никакой информации или знаний о разрабатываемой вами системе.

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

Уэйн Вернер
источник
2

Вам следует воздержаться от этого, если у вас нет веской причины.

Один файл с несколькими небольшими связанными классами может быть более читаемым, чем несколько файлов. Например, при использовании «классов случаев» для имитации типов объединения между каждым классом существует сильная взаимосвязь. Использование одного и того же файла для нескольких классов имеет преимущество в том, что они визуально группируются для читателя.

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

Жуткая головоломка
источник
1

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

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

Робин
источник
1

Ответ Smalltalk: у вас не должно быть файлов (для программирования). Они затрудняют управление версиями и навигацию.

Стефан Эггермонт
источник