Якщо у вас є логіка, яку потрібно розділити між двома контролерами, де ви її зберігаєте?


10

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


CakePHP називає їх Компоненти: book.cakephp.org/2.0/en/controllers/components.html можливо, це є деяким натхненням.
Люк Франкен

Відповіді:


12

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

Не рідкість мати клас корисності або клас помічника, залежно від вашої структури. Наприклад, у веб-рамках Java та C # ви можете мати пакет / простір імен для утиліт. У Ruby on Rails ви можете скористатися Helperкласом, який розділяє логіку між контролерами та видами. В основному, це виглядатиме так:

// NOTE: group similar functions
static class LoginUtility
{
    static bool IsLoggedIn(Request request) { /* ... */ }
}

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

В будь-якому випадку ви отримаєте доступ до нього у кожному з своїх контролерів, як це:

void MyAction()
{
    if (LoginUtiltiy.IsLoggedIn(Request))
    {
        // Do something ...
    }
}

Оригінальний відповідь

Ви не сказали, що це за ваша платформа, оскільки це може вплинути на відповідь. Припускаючи, що це об'єктно-орієнтована мова, найпоширенішим підходом є створення базового класу, який розширюють обидва контролери. Наприклад, у Ruby on Rails:

class BaseController < ApplicationController
    def my_special_function
        # ...
    end
end

class Controller1 < BaseController
    # ...
end

class Controller2 < BaseController
    # ...
end

Ви можете перекласти ідею і на інші мови. Цей же підхід буде працювати і для ASP.NET MVC, Apache Wicket, Grails, або майже будь-який інший об'єктно-орієнтований веб-фреймворк. Якщо ваша мова не орієнтована на об’єкти, то це дійсно залежить від того, як буде розроблена рамка як найкращий підхід.


3
Альтернативою є інкапсуляція логіки в окремий клас, а потім інстанціювати цей клас та викликати логіку з обох контролерів.
Крамій

5
Так, я завжди віддаю перевагу складу над спадщиною
Рено,

1
Робіть пропозицію Крамія, а не додайте зайвий шар спадку. Але я думаю, що його актуальним питанням було те, куди в рішенні йде цей клас.
Ніхто

1
Це залежить від того, яка функція та рамки. У рейках це може належати до класу Хелпер. В ASP.NET або Java у вас може бути клас утиліти для цього типу функцій. Це дійсно залежить від того, наскільки близько до контролера йому потрібно жити.
Берін Лорич

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