У MVC чи вважається хорошою практикою мати приватні функції без дії в класі контролера?


10

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

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

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

Відповіді:


16

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

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

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


+1 для творчої аналогії. :) Ви робите цікавий момент. Особливо щодо формування шкідливої ​​звички. Дякую.
Девід 'лисий імбир'

8

Найкраща відповідь, яку я можу дати, - це цитувати велику книгу Роберта Мартіна "Чистий код", яку я дуже рекомендую всім, хто цікавиться цією темою:

Перше правило функцій полягає в тому, що вони повинні бути невеликими. Друге правило - вони повинні бути меншими за це.

Не можу сказати, що краще. Ще одна чудова цитата з цієї ж книги стосується:

Функції повинні виконувати одне. Вони повинні це зробити добре. Вони повинні робити це лише.

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

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


1
Я не думаю, що введення бізнес-логіки у погляди - це "некласичний MVC", це просто "поганий MVC". Очевидно, що вам потрібні основні структури управління у видах, але вони повинні бути узгоджені з питаннями користувача / інтерфейсу користувача, а не з питаннями щодо домену / бізнесу. Фактична функція в погляді є досить жахливою.
Aaronaught

1
@Aaronaught Я був розпливчастим з "деякою логікою", я мав на увазі, наприклад, бібліотеку Backbone.js, де ви розміщуєте події та функції користувачів, щоб обробляти їх на ваш погляд. У класичному MVC це робота контролера. Однак це може бути непрактично, оскільки вам потрібно буде налаштувати і View, і Controller щоразу, коли ваш інтерфейс змінюється. Встановивши функції обробника інтерфейсу в Перегляд, вам потрібно лише налаштувати Перегляд. Це лише мій суб'єктивний погляд - я щось пропускаю?
Дмитро Зайцев

1
Просто те, що щось доставляється на стороні клієнта, не означає, що це логічно є частиною перегляду. Прив’язка даних у представленнях, безумовно, але Backbone - сама структура MV * (вид MVC, тип MVP, не зовсім) і сценарії на стороні клієнта повинні бути організовані відповідно; в іншому випадку ти просто зламаєш.
Aaronaught

0

У MVC я намагаюся переконатися, що мій контролер максимально тонкий, а також, щоб мої моделі були максимально німими.

Логічні та допоміжні функції, які потрібні, складаються в окремі самостійні класи помічників. Це також робить моє тестування набагато простішим (ви тестуєте .. правильно?: D) Тестування контролерів, як відомо, важко. Кожен раз, коли ви намагаєтеся створити екземпляр контролера для тестування, ви повинні думати про HTTP-контекст і підробляти http це і те, і його біль, але його біль за призначенням. Вам потрібні всі ці речі, оскільки контролер настільки тісно пов'язаний з HTTP та Інтернетом. Це точка входу у ваш веб-додаток.

Логічні та допоміжні функції не мають нічого спільного з Інтернетом. Вони повністю агностичні в оточенні (або вони повинні бути). Це одне повинно сказати вам, що вони не належать разом в одному місці. Плюс, якщо ви зв’язуєте всі свої логічні програми так близько до Інтернету чи певної веб-реалізації, ви ніколи не можете взяти її з собою.

Ми розробили наш веб-сайт MVC з усіма нашими базами даних (не з нашими моделями mvc, нашими фактичними db-сутностями), нашим сховищем, нашими допоміжними класами та нашою логікою в окремих окремо взятіх DLL. У нас тільки кожен мав один веб-сайт, але ми все одно зробили це так.

Кілька місяців тому нас попросили створити кілька настільних додатків, які стосуються кількох наших систем бахроми. Це було легко зробити, оскільки весь тестований код можна було легко використати повторно. Якби ми внесли наш код у наш веб-проект або ввели його в контролери, ми б ніколи цього не змогли зробити.


2
Модель MVC - єдиний шар, який не повинен бути німим. Якщо розумних моделей немає, і вони не в контролері, то де вони ... на думку? Контролери також не повинні бути важкими для тестування; Можливість використання DI та підробок / макетів для полегшення тестування одиниць є одним із малюнків MVC над іншими рамками. Більшість тестів мого контролера проходять під 5 рядками.
Aaronaught

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

У мене є відчуття, що ця відповідь означає добре, але вона написана неправильно .. або, можливо, різною термінологією.
Саймон Уайтхед

3
Класи «помічники» не є архітектурним елементом. Вони або частина M, V або C. Якщо ви не впевнені в чому, то ці помічники не мають згуртованості . Слово "помічник" також займає місце там із "ручкою", "робити", "виконувати" та бояться менеджера .
Aaronaught

@SimonWhitehead: Більшість відповідей означають добре, але багато хто невірні. Цей, на жаль, або пропагує нерозуміння значення "моделі", або рекомендує висувати критичну ділову логіку поза нею. Я мав сумнівну насолоду підтримувати сайти MVC із мільйоном "помічників" - вони жахливі.
Aaronaught

-2

Окрім Дмитра Зайцева та космонавта чудові відповіді, я не знаю, чи справедливим є також і для PHP: Вам слід намагатися уникати приватних методів через відсутність автоматизованих можливостей тестування.

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

Завжди пам’ятайте про принцип KISS: Тримайте це просто, дурно.


5
Це не є вагомою причиною уникнення приватних методів, а також не має нічого спільного з архітектурою MVC. Ви не намагаєтеся перевірити приватні методи, вони повинні бути охоплені тестами на публічні методи. Якщо ви не можете їх охопити, то це знак того, що ваш клас занадто складний і його потрібно реконструювати; це не означає, що у вас не повинно бути приватних методів або (я щиро сподіваюся, що це не те, що ви насправді мали на увазі), що вони повинні бути загальнодоступними.
Aaronaught
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.