Переработка OOP кода в MVC паттерн

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

Для того, чтобы лучше разобраться в этом. Возможно мне поможет переработанный пример кода в ООП стиле на MVC.
Я хотел бы знать, как можно переработать этот класс Car для отображения в шаблоне MVC? И как будут реализованы связи, если я захочу использовать методы Go() и Stop() из любого скрипта? Я хочу, чтобы эти методы работали при нажатии клавиши на клавиатуре и так же нажатии кнопки на экране. Кроме того, через некоторое время после вызова метода Go() должен сработать метод Stop(). public Car myCar;

static void Main()
{
    myCar = new Car("BMW", 2009, "Black");
}

public class KeyInput() {
    private void OnPressKeyG() {
        myCar.Go();
    }
}

public class CarButton() {
    public void OnClickButtonGo() {
        myCar.Go();
    }
}

public class Car {
    private string _model;
    private int _yearBuy;
    private string _color;
    public Car(model, yearBuy, color) {
        this._model = model;
        this._yearBuy = _yearBuy;
        this._color = _color;
    }
    public void Go() {
        // Go.    
    }
    public void Stop() {
        // Stop.    
    }
    public void ChangeColor(newColor) {
        _color = newColor;
    }
    private void DelayStop() { // Some delay.         
        Go();
    }
}

Спасибо!


Ответы (1 шт):

Автор решения: Гончаров Александр

MVC - это идеология. Никаких жёстких рамок для его использования нет, в общем то: поэтому в детали не обязательно углубляться, как вы решите у себя в проекте, такие взаимодействия и будут разрешены.

Например, могу ли я вызывать любой компонент MVC из службы? Контроллер должен так же может выполнять функции типа void, которые могут вызываться из других скриптов, почему в фреймворке CodeIgniter нельзя вызвать контроллер из другого контроллера и тд.?

Вызов контроллером другого контроллера - в Zend для этого есть forward (то есть перебросить выполнение, из одного контроллера, на другой) очень удобно, например для вывода ошибок, или наоборот сообщений об успехе.

Или у вас есть контроллер, например, для регистрации юзеров - а вам надо из другого контроллера зарегать их 1000: нужно в цикле сконструировать контроллер регистрации, объекты запроса, ответа, и выполнять. Или даже не конструируя, выполнить действия контроллера через curl (http-запросы на свой-же сервис). Сам так делал, обоими способами.

Но лучше этим не злоупотреблять - потому что контроллер таким образом превратится в сборник функций. А он должен представлять собой сборник законченных действий для внешних пользователей вашего сервиса (то есть для web-клиента, если мы про web), как API. Переиспользуемые же внутри кода функции: гораздо лучше смотрятся в моделях, а также в других вспомогательных классах, утилитах.

хотел бы знать, как можно переработать этот класс Car для отображения в шаблоне MVC?

Класс-пример, который вы предлагаете переработать - очень неудачный: по сути, это и есть модель, буква M из словосочетания MVC . Вам нужно взять что-то в пример из областей, где реально используется MVC - из веба, а абстрактную фантазию из серии "как натянуть ужа на ежа" мало кому охота включать . Но я попробую.

Допустим ваша машина живёт в web (язык бекенда PHP, коде-игнитер вроде пхп ведь). Тогда все её данные хранятся где-то например в БД , или в файле на сервере; _model _yearBuy _color - конкретно они будут принадлежать модели M. Контроллер C - будет разбит на действия GoAction и StopAction . При вызове метода GoAction с запланированной остановкой - может происходить просто вызов метода модели Go($stopSeconds), а в нём уже:

$this->engineWorking = true;
$this->stopTimestamp = time() + $stopSeconds;
$this->save();
/*Важно - модель никогда не использует переменные напрямую из запроса 
- нужные переменные подсовывает в аргументы метода модели сам контроллер.*/

Контроллер C также передаёт данные о машине в вид.

$this->view->carData = $car->toArray();

Вид V(в данном случае - один на 2 экшена контроллера), простой html c PHP-вставками, соответственно рендерит всё, что происходит: состояние машины. В его JS выводится

var carData = <?=json_encode($this->carData)?>;

Также он понимает точку отсчёта времени:

var serverTime = <?=time()?>;

Чтобы корректно отрендерить запланированную остановку(переключить состояние кнопок по наступлению stopTimestamp). А также содержит в себе две кнопки Поехали и Стоп. В зависимости от того, едет машина, или стоит - можно нажать одну из этих двух кнопок. Cостояние кнопок может поменяться без участия юзера - по наступлению stopTimestamp.

Нажатие кнопки вызывает ajax-запрос, который направляется на StopAction или на GoAction , после чего страница, например, перезагружается (меняет весь свой HTML на то, что вернул ajax).

Вот и всё. Но это слишком игрушечный пример - на таком вы не сможете понять, зачем нужен MVC . На гитхабе, наверняка, есть проекты - количество экшенов в сумме под 500 , и количество моделей под 100 : вот вам надо развернуть такой, и плотно поиздеваться над ним. Вся суть в том - что контроллеры независимы друг от друга - а вся связь между ними, идёт через ссылки/скрипты видов(которые дёргают эти контроллеры по http), то есть вся связь между контроллерами идёт через пользовательские действия. И виды так-же независимы друг друга. Модели часто связаны, но лишь внутри своих методов, и глобальной системы кеширования у фреймворка. В итоге, вам очень сложно что-то сломать во всей системе, если вы правите один контроллер, или один вид, или даже модель( при этом следуя правилу Лискин - модифицируй так, чтобы старое работало неизменно ). Как устроены классы, дело десятое, как нравится вам/фреймворку их вообще может не быть в MVC (или по минимуму - только для моделей), и MVC будет работать.

И никто не запрещает пользоваться при MVC вспомогательными классами , как например утилиты, диспетчеры событий, классы для форм(валидация/рендеринг), общие функции для контроллеров - которые не ассоциируются с БД, и.т.д.

→ Ссылка