Чи погана практика мати кілька класів в одному файлі?


82

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

Моє запитання підходить для Java, C #, PHP або будь-якої іншої мови програмування. Чи слід намагатися не мати декількох класів в одному файлі, чи це нормально?

Відповіді:


94

Я думаю, вам слід спробувати зберегти свій код до 1 класу на файл.

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

Єдиний раз, коли я вважаю правильним використовувати більше одного класу для файлу, це коли ви використовуєте внутрішні класи ... але внутрішні класи знаходяться всередині іншого класу, і тому їх можна залишити всередині того самого файлу. Ролі внутрішніх класів тісно пов'язані із зовнішніми класами, тому розміщення їх у одному файлі є чудовим.


1
Побачивши, що Kotlin може зробити в одному файлі, я починаю вірити, що деякі речі, такі як DTO, можуть бути в одному файлі.
John Tribe

1
До того ж, класи, які ви мали б в одному файлі, зазвичай тісно пов’язані, що може ускладнити редагування, оскільки не так просто переглядати кілька класів одночасно. Вам доведеться багато прокручувати. Розділений вигляд допомагає, але це не так просто, як просто мати окреме вікно для кожного файлу / класу.
Чад Хеджкок,

А як щодо автозавантаження? При визначенні кількох класів в одному вихідному файлі функція автоматичного завантаження стане більш складною. див. 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
Ні. Це погана порада. Скористайтесь порадою прийнятої відповіді. Вам слід відокремити сховище об’єктів від класу, який ви зберігаєте. Це просто створює необов’язкову плутанину.
Хадсон,

4
@Hudson Я не бачу жодного коду "сховища об'єктів" вище.
Ryan Lundy

18

Ні, я не вважаю це абсолютно поганою практикою. Що я маю на увазі під цим, загалом найкраще мати окремий файл для кожного класу, але, безумовно, є добрі випадки винятків, коли краще мати купу класів в одному файлі. Хорошим прикладом цього є група класів винятків, якщо у вас є кілька десятків таких для даної групи, чи справді має сенс окремий файл для кожного двох класів вкладишів? Я б сперечався, що ні. У цьому випадку наявність групи винятків в одному класі набагато менш громіздка та проста IMHO.


10

Я виявив, що всякий раз, коли я намагаюся об’єднати декілька типів в один файл, я завжди закінчую повертатися назад і розділяти їх просто тому, що це полегшує їх пошук. Кожного разу, коли я комбіную, завжди є кінцевий момент, коли я намагаюся зрозуміти, wtf я визначив тип x.

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


9

Оскільки ваш IDE надає вам функцію " Перейти до ", і ви маєте певний контроль над простором імен у своїх класах, то нижченаведені переваги наявності декількох класів в одному файлі для мене цілком варті.

Класи для батьків та дітей

У багатьох випадках мені дуже корисно мати спадкові класи у їхньому файлі базового класу.

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

Громадські: малі - допоміжні - класи DTO

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

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

Загалом порушення правила Iron 1 класу на файл надає додаткову свободу в організації вашого коду.

Що станеться тоді, насправді залежить від вашої IDE, мови, командного спілкування та навичок організації.

Але якщо ти хочеш цієї свободи, навіщо жертвувати нею за залізне правило?


7

Якщо ви працюєте в команді, ведення класів в окремих файлах полегшує керування джерелом та зменшує ймовірність конфліктів (кілька розробників змінюють один і той же файл одночасно). Я думаю, це також полегшує пошук коду, який ви шукаєте.


7

Правило, якого я завжди дотримуюся, - це мати один основний клас у файлі з однаковим ім’ям. Я можу включати або не включати в цей файл допоміжні класи залежно від того, наскільки тісно вони поєднані з основним класом файлу. Класи підтримки є автономними, чи вони корисні самі по собі? Наприклад, якщо метод у класі потребує спеціального порівняння для сортування деяких об’єктів, мені не заважає об’єднати клас функтора порівняння у той самий файл, що і метод, який його використовує. Я б не сподівався використовувати його в іншому місці, і немає сенсу, щоб він був самостійним.


6

Це може бути погано з точки зору майбутнього розвитку та ремонтопридатності. Набагато легше згадати, де знаходиться клас Car, якщо у вас є клас Car.cs. Де б ви шукали клас Widget, якщо Widget.cs не існує? Це віджет автомобіля? Це віджет двигуна? О, можливо, це віджет бублика.


2
Як згадувалося в stackoverflow.com/questions/360643/… , із загальними інструментами навігації вам все одно не потрібно переходити за файлом. Ви замість цього здійснюєте навігацію за класами / учасниками.
Сума,

6

Тільки раз , коли я вважаю розташування файлів, коли я повинен створити нові класи. В іншому випадку я ніколи не переходжу за структурою файлу. Я використовую "перейти до класу" або "перейти до визначення".

Я знаю, що це певне питання навчання; звільнення від фізичної файлової структури проектів вимагає практики. Це дуже корисно;)

Якщо вам хочеться помістити їх в один файл, будьте моїм гостем. Не можу це зробити з публічними класами в Java;)


2

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


2

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

Наприклад, яка згуртованість цих класів? Вони тісно пов’язані? Вони повністю ортогональні? Чи пов’язані вони за функціональністю?

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

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

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

Мабуть, найкращим емпіричним правилом є не обмежувати свій вибір еркемічним правилом. Емпіричні правила створені для першого аналізу або для обмеження вибору тих, хто не здатний зробити гарний вибір. Думаю, більшість програмістів хотіли б вірити, що вони здатні приймати правильні рішення.


2

Вам слід утриматися від цього, якщо у вас немає вагомих причин.

Один файл із декількома невеликими пов'язаними класами може бути читабельнішим, ніж кілька файлів. Наприклад, при використанні 'класів case' для імітації типів об'єднання існує сильний зв'язок між кожним класом. Використання одного і того ж файлу для кількох класів має перевагу у тому, що їх візуально згрупувати для читача.

У вашому випадку машина та двері взагалі не схожі, і пошук класу дверей у файлі car.cs буде несподіваним, тому не робіть.


1

Один клас на файл простіший в обслуговуванні та набагато зрозуміліший для всіх, хто дивиться на ваш код. Це також є обов’язковим або дуже обмеженим для деяких мов.

Наприклад, в Java ви не можете створити кілька класів верхнього рівня для одного файлу, вони повинні знаходитися в окремих файлах, де назва класу та ім'я файлу однакові.


1

Відповідь Smalltalk така: у вас не повинно бути файлів (для програмування). Вони роблять версії та навігацію болючими.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.