Теория
Если коротко, то MVC (model view controller) это такой способ написания программы, когда код отвечающий за вывод данных, пишется в одном месте, а код который эти данные формирует, пишется в другом месте. В итоге получается так, что если вам надо подправить вывод вы сразу знаете в каком месте искать. Сейчас все популярные фреймворки используют такую архитектуру.
Также стоит упомянуть тот факт, что существует два лагеря: один пишет логику в контроллерах, второй в моделях. В тех фреймворках, которые знаю я (yii, laravel) логику пишут в контроллерах, а модели являются просто экземплярами ORM (почитайте про паттерн Active Record). У yii кстати в мануале написано, что писать логику надо в моделях, а потом они сами в примерах пишут её в контроллерах, довольно забавно.
С бизнес-логикой определились, пишем в контроллерах. Также в методах контроллера происходит вызов моделей, которые у нас по сути экземпляры ORM, чтобы с их помощью получить данные из базы над которыми будут производить изменения. Конечный результат отправляется в виды. Виды cодержат HTML-разметку и небольшие вставки PHP-кода для обхода, форматирования и отображения данных.
Ещё можно упомянуть, что есть два вида MVC Page Controller и Front Controller. Page Controller'ом пользуются редко, его подход заключается в использовании нескольких точек входа (запросы к сайту осуществляются к нескольким файлам), и внутри каждой точки входа свой код отображения. Мы будем писать Front Controller с одной точкой входа.
Практика
Начать надо с настройки сервера для переадресации на нашу единую точку входа. Если у нас apache, то в файле .htaccess пишем следующее
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
Дальше в папке нашего проекта создаём папку, которую можно назвать App например. В ней будет следующее содержимое.
Наш Service Locator. Файл App.php
<?php
class App
{
public static $router;
public static $db;
public static $kernel;
public static function init()
{
spl_autoload_register(['static','loadClass']);
static::bootstrap();
set_exception_handler(['App','handleException']);
}
public static function bootstrap()
{
static::$router = new App\Router();
static::$kernel = new App\Kernel();
static::$db = new App\Db();
}
public static function loadClass ($className)
{
$className = str_replace('\\', DIRECTORY_SEPARATOR, $className);
require_once ROOTPATH.DIRECTORY_SEPARATOR.$className.'.php';
}
public function handleException (Throwable $e)
{
if($e instanceof \App\Exceptions\InvalidRouteException) {
echo static::$kernel->launchAction('Error', 'error404', [$e]);
}else{
echo static::$kernel->launchAction('Error', 'error500', [$e]);
}
}
}
Сервис локатор нужен чтобы хранить в нём компоненты нашего приложения. Поскольку у нас простое mvc приложение, то мы не используем паттерн registry (как например в yii сделано). А просто сохраняем компоненты приложения в статические свойства, чтобы обращаться к ним было проще. Ещё App регистрирует автозагрузчик классов и обработчик исключений.
Роутер. Файл Router.php
<?php
namespace App;
class Router
{
public function resolve ()
{
if(($pos = strpos($_SERVER['REQUEST_URI'], '?')) !== false){
$route = substr($_SERVER['REQUEST_URI'], 0, $pos);
}
$route = is_null($route) ? $_SERVER['REQUEST_URI'] : $route;
$route = explode('/', $route);
array_shift($route);
$result[0] = array_shift($route);
$result[1] = array_shift($route);
$result[2] = $route;
return $result;
}
}
В простом mvc приложении роутер содержит всего один метод. Он парсит адрес из $_SERVER['REQUEST_URI']. Я ещё не сказал, что все наши ссылки на страницы сайта должны быть вида www.ourwebsite.com/%controller%/%action%, где %controller% — имя файла контроллера, а %action% — имя метода контроллера, который будет вызван.
Файл Db.php
<?php
namespace App;
use App;
class Db
{
public $pdo;
public function __construct()
{
$settings = $this->getPDOSettings();
$this->pdo = new \PDO($settings['dsn'], $settings['user'], $settings['pass'], null);
}
protected function getPDOSettings()
{
$config = include ROOTPATH.DIRECTORY_SEPARATOR.'Config'.DIRECTORY_SEPARATOR.'Db.php';
$result['dsn'] = "{$config['type']}:host={$config['host']};dbname={$config['dbname']};charset={$config['charset']}";
$result['user'] = $config['user'];
$result['pass'] = $config['pass'];
return $result;
}
public function execute($query, array $params=null)
{
if(is_null($params)){
$stmt = $this->pdo->query($query);
return $stmt->fetchAll();
}
$stmt = $this->pdo->prepare($query);
$stmt->execute($params);
return $stmt->fetchAll();
}
}
Этот класс юзает файл конфига, который возврашает массив при подключении
Файл Config/Db.php
<?php
return [
'type' => 'mysql',
'host' => 'localhost',
'dbname' => 'gotlib',
'charset' => 'utf8',
'user' => 'root',
'pass' => ''
];
Наше ядро. Файл Kernel.php
<?php
namespace App;
use App;
class Kernel
{
public $defaultControllerName = 'Home';
public $defaultActionName = "index";
public function launch()
{
list($controllerName, $actionName, $params) = App::$router->resolve();
echo $this->launchAction($controllerName, $actionName, $params);
}
public function launchAction($controllerName, $actionName, $params)
{
$controllerName = empty($controllerName) ? $this->defaultControllerName : ucfirst($controllerName);
if(!file_exists(ROOTPATH.DIRECTORY_SEPARATOR.'Controllers'.DIRECTORY_SEPARATOR.$controllerName.'.php')){
throw new \App\Exceptions\InvalidRouteException();
}
require_once ROOTPATH.DIRECTORY_SEPARATOR.'Controllers'.DIRECTORY_SEPARATOR.$controllerName.'.php';
if(!class_exists("\\Controllers\\".ucfirst($controllerName))){
throw new \App\Exceptions\InvalidRouteException();
}
$controllerName = "\\Controllers\\".ucfirst($controllerName);
$controller = new $controllerName;
$actionName = empty($actionName) ? $this->defaultActionName : $actionName;
if (!method_exists($controller, $actionName)){
throw new \App\Exceptions\InvalidRouteException();
}
return $controller->$actionName($params);
}
}
Ядро обращается к роутеру, а потом запускает действия контроллера. Ещё ядро может кинуть исключение, если нет нужного контроллера или метода.
Файл Controller.php
Ещё нам нужно создать базовый класс для наших контроллеров, чтобы потом наследоваться от него. Наследовать методы нужно для того, чтобы вы могли рендерить (сформировать вывод) виды. Методы рендеринга поддерживают использование лэйаутов — шаблонов, которые содержат общие для всех видов компоненты, например футер и хэдер.
<?php
namespace App;
use App;
class Controller
{
public $layoutFile = 'Views/Layout.php';
public function renderLayout ($body)
{
ob_start();
require ROOTPATH.DIRECTORY_SEPARATOR.'Views'.DIRECTORY_SEPARATOR.'Layout'.DIRECTORY_SEPARATOR."Layout.php";
return ob_get_clean();
}
public function render ($viewName, array $params = [])
{
$viewFile = ROOTPATH.DIRECTORY_SEPARATOR.'Views'.DIRECTORY_SEPARATOR.$viewName.'.php';
extract($params);
ob_start();
require $viewFile;
$body = ob_get_clean();
ob_end_clean();
if (defined(NO_LAYOUT)){
return $body;
}
return $this->renderLayout($body);
}
}
Файл index.php
Не забываем создать индексный файл в корне:
<?php
define('ROOTPATH', __DIR__);
require __DIR__.'/App/App.php';
App::init();
App::$kernel->launch();
Создаём контроллеры и виды
Работа с нашим приложением (можно даже сказать минифреймворком) теперь сводится к созданию видов и контроллеров. Пример контроллера следующий (в папке Controllers):
<?php
namespace Controllers;
class Home extends \App\Controller
{
public function index ()
{
return $this->render('Home');
}
}
Пример вида(в папке Views):
<img src="Img/my_photo.jpeg" alt="my_photo" id="my_photo">
<h1>Привет</h1>
<p>Меня зовут Глеб и я - веб-разработчик.</p>
Мои контакты:<br>
8-912-641-3462<br>
goootlib@gmail.com
В папке Views/Layout создаём Layout.php:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Обо мне</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="/Css/style_layout.css" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed" rel="stylesheet">
</head>
<body>
<header>
<nav>
<a id="about_button" href="/home">Обо мне</a>
<a id="portfolio_button" href="/portfolio">Портфолио</a>
<a id="blog_button" href="/blog">Блог</a>
</nav>
</header>
<div class="main">
<?= $body ?>
</div>
<footer>
<div class="copyrights">
2017 Жуков Глеб(gotlib)<br>
При копировании материалов на сторонние ресурсы, ссылка на http://www.gotlib.info обязательна!
</div>
<div class="contacts">
8-912-641-3462<br>
goootlib@gmail.com
</div>
</footer>
</body>
</html>
Заключение
Если решите пользоваться кодом приложения, которое описал я, не забудьте создать контроллер Error с методами error404 и error500. Класс для работы с бд, описанный мной, подходит для написания запросов руками, вместо него можно подключить ORM и вас будут настоящие модели.
Комментарии (61)
SamDark
26.01.2017 13:13В тех фреймворках, которые знаю я (yii, laravel) логику пишут в контроллерах, а модели являются просто экземплярами ORM (почитайте про паттерн Active Record). У yii кстати в мануале написано, что писать логику надо в моделях, а потом они сами в примерах пишут её в контроллерах, довольно забавно.
Очень был бы благодарен за указания на конкретные места в гайде Yii, которые:
- Рекомендуют писать логику в контроллерах.
- Показывают логику в контроллерах (скорее всего ради упрощения сделано).
- Рекомендуют писать логику в Active Record или намекают на это.
- Говорят, что AR === модель.
У меня, как автора довольно значительной части этих текстов, развилась слепота на ошибки :(
А вообще вот что я об этом думаю: https://github.com/samdark/yii2-cookbook/blob/master/book/mvc.md
Zazza
26.01.2017 15:20Есть такая тема про толстые контроллеры/модели и этому в значительной части подвержен именно yii. Но в этом виновата не документация, а огромное число проектов с такими подходами. Я даже видео по фреймворку видел, где делают именно так: логику пишут в контроллере, а модели максимально загружают различными вызовами. Еще и минус php как шаблонизатора (1-й yii), вставить виджет на страницу, а перед ним код прямо в шаблоне.
Раз у вас есть опыт написания статей, м.б. написать статью с примерами хороших подходов: соблюдение PSR-ов, создание либ для помещения логики, и если рассматривать yii можно запихнуть, как хорошо организовывать конфиги и структуру папок проекта и т.д.?SamDark
26.01.2017 18:59Я это делаю время от времени. Недавно рассказывал в Иванове про это. Ссылки и видео тут: http://slides.rmcreative.ru/
Статьи тоже пишу, выше ссылка как раз.
VolCh
26.01.2017 22:01М — это прежде всего классы и функции, содержащие бизнес-данные в рантайме и реализующие бизнес-логику. Как данные туда попадают, куда деваются и откуда запускаются функции и методы классов к М особого отношения не имеет, даже если классы основных сущностей наследуют какой-нибудь АктивРекорд.
Zazza
26.01.2017 22:58+1что во всех подобных разговорах мне не нравится, код в первую очередь должен быть понятен. Не важно M это или нет, проблема толстых контроллеров и моделей именно в в уложении восприятия, а уж где и как, что будет располагаться это вообще мало важно, я могу в контроллере использовать приватные функции, лишь бы это было логично и понятно. А то устроили какую-то религию из этого ))
oxidmod
26.01.2017 23:05Это не религия, это просто следующий шаг после отделения логики от представления. Слоеная архитектура, как её называют. бизнес-логика должна быть в бизнес слое, чтобы не зависеть от контролера, бд, фреймворка.
Zazza
26.01.2017 23:22+1Я же не говорил писать в представлкнии. Я сказал, что код должен быть понятным. Все зависит от ситуации. Вы говорите теорию.
SamDark
26.01.2017 23:30+1Да, всё так. К сожалению, код становится непонятным сразу по двум причинам:
- Когда его слишком много и он делает всё и сразу.
- Когда абстракции слишком много, каждая отдельная часть кода слишком проста, а взаимодействие частей слишком сложно.
VolCh
27.01.2017 00:04+1Один из факторов понятности — контекст, в том числе именование, в том числе место расположения в проекте. Один кусок кода будет понятнее в папочке/классе Controller, а другой в Model.
http3
26.01.2017 15:59Большинство фреймворщиков (писунов в интернетах) именно так неправильно и понимают M.
Типо, M — это наследник базового класса по работе с базой и этот M расширяют всяким мусором. :)
А что плохого, если простая логика будет в контроллере?
Если M ограничится ORM? :)
Temirkhan
26.01.2017 18:28Все-таки, когда я только начинал, мне тоже везде попадались примеры с толстымиконтроллерами.
Но с другой стороны, если почитать в самому низу
документации(параграф BestPracice), правда на Вашей стороне…
К тому же, в доках и демках практически все известные мне фреймворки грешат этим. Тот же laravel, тот же symfony. Полагаю, это связано с привлечением внимания большей части аудитории.(порог вхождения, все дела)SamDark
26.01.2017 19:01Не, это просто несколько разгружает доку. Если каждый раз заворачивать всё в нормальный бизнес-слой, дока будет про него, а не про то, что сказать хотели.
CnapoB
26.01.2017 13:33+1Слишком часто последнее время попадается подобный код, который они гордо называют MVC, в качестве портфолио от соискателей.
Так что если вы новичок и хотите начать писать программы правильно, читайте дальше.
— array_shift слишком затратная функция (извлечь + сдвинуть все элементы с числовыми индексами), вместо нее лучше обращаться напрямую через [], либо, если так уж хочется удалять элементы из массива, то array_reverse + array_pop, а конкретно в вашем примере $result=explode('/',$route,3);
— Судя по тому, как добавляются файлы через require, документация к нему прочитана не была.
— Функция launchAction накладывает ограничения на названия файлов и классов.
— Об использовании двойных кавычек вообще молчу.
ИМХО: И представленный код не для новичков с его namespace и классами. Если вы действительно хотели написать гайд, начали бы с процедурного стиля.
AlexLeonov
26.01.2017 13:49+1class Controller { public $layoutFile = 'Views/Layout.php';
Кол вам за тему «MVC», приходите пересдавать.
MadridianFox
26.01.2017 14:39+2Так что если вы новичок и хотите начать писать программы правильно, читайте дальше.
С бизнес-логикой определились, пишем в контроллерах.
Одного только этого достаточно, чтобы сказать, что польза от данного текста скорее отрицательна.
akubintsev
26.01.2017 18:30Только мне одному кажется сегодня чем-то диким заморачиваться на тему MVC и какой архитектуре/паттерну соответствует код?
Может люди живут в идеальном мире с только новыми и хорошо написанными проектами? Или где-то водятся в большом количестве компании, щедро бюджетирующие непродуктовые задачи типа рефакторинга?
Расслабьтесь и получайте удовольствие: в реальном мире нереальное количество говнокода. Процедурного из эпохи 5.2 и псевдо-ООП из 5.3. Чему и нужно учиться, так это как выживать среди всего этого бедлама, сводя к минимуму факапы и намазывая поверх код с новыми бизнес-фичами.SerafimArts
26.01.2017 18:35+1Это ваше личное мнение. Лично я уже лет 5 подобного не видел. На проде нынче только php 7+, максимум php 5.6. Совет — меняйте работу.
akubintsev
26.01.2017 19:04Я за свои 7 лет в вебе как раз встречал больше плохого, чем хорошего. И это логично, поскольку многие проекты писались в старую эпоху и разработчиками, которые не рвались переучиваться на новый лад.
А что вы скажете, если разработчик придёт работать в компанию, где портал крутится на wordpress? Там и по сей день новый версии не блещут красивым кодом даже на фоне joomla.
Работу менять только из-за плохого кода считаю эскапизмом. Есть множество и других определяющих факторов.SerafimArts
27.01.2017 00:44А что вы скажете, если разработчик придёт работать в компанию, где портал крутится на wordpress? Там и по сей день новый версии не блещут красивым кодом даже на фоне joomla.
Это опять же конкретно ваши неудача, что попадались такие проекты и переходили на такие работы. За более чем 5 лет работы (может меньше, может больше, начинал во времена php 5.2) мне ни разу не встретилась та, где использовались бы какие-нибудь CMS или просто код в стиле php 4.
Да, может я излишне цинично рассматриваю этот вопрос, не учитывая каких-то факторов, но вы сами определяете где и кем будете работать. Если вам нравится работать с битриксоподобными продуктами — это ваше личное предпочтение.
Наличие подобной кодовой базы обусловлено, либо откровенно наплевательским отношением к проекту, либо технической безграмотностью специалистов. В любых случаях, работать в таких местах ради своего развития (т.к. именно это является наиболее критичным фактором для подбора любой работы) я бы не стал.
Ещё раз прошу прощения за цинизм. Но стоит развиваться, чтобы вас оценивали как специалиста, а не бежать в первое попавшееся место.
http3
27.01.2017 10:51Если вам нравится работать с битриксоподобными продуктами
Хм, но какая разница, что внутри CMS или фреймворка? :)
С этим кодом разработчику работать не приходится.
А вот на якобы нормальных CMS или фреймворках программисты создают свой говнокод, с которым приходится работать другим. :)michael_vostrikov
27.01.2017 11:24Разница в том, как использовать то, что внутри. Насколько это удобно и понятно. И какие дает возможности.
http3
27.01.2017 11:35Внутри черный ящик с публичным API.
API битрикса — более менее норм. А также его плюс в том, что оно обратно совместимо.
А вот когда куча говнокода на якобы нормальном фреймворке — вот это печально.
Методы CMS или фреймворка не так и часто нужно использовать.
akubintsev
27.01.2017 11:45Да всё нормально, я понимаю вашу позицию. У меня был опыт в «долгом» стартапе и это было прекрасное время, когда всё писалось красиво с нуля на самых передовых технологиях. Но стартап умер, как это часто и бывает.
С каждым годом ситуация с проектами становится лучше, но про вордпресс я не зря упомянул, поскольку это одна из самых популярных CMS в мире PHP на сегодня, а значит и шансы встретиться с ней велики.
На это конечно можно возразить, что подобные CMS используют только в маленьких компаниях. Ок, давайте тогда рассмотрим большие компании. В больших компаниях большие и долгоживущие проекты. Я трижды попадал в такие и во всех случаях был самописный велосипед. В одном вообще хаос и анархия, оттуда быстро убежал (2012 год). В другом (2015) вроде получше были ситуация, стали потихоньку переписывать с процедур на псевдоООП. И наконец в последней компании процедурный стиль, но хотя бы с каким-то намеком на архитектуру, но конечно же без единого теста.
Я соглашусь с тем, что на определенных этапах развития, особенно раннем, лучше сменить работу. Но когда уже есть опыт разработки и выработано чувство прекрасного, а всё остальное в работе, кроме кода, устраивает, в том числе и карьерная перспектива, то есть резон продолжать трудиться на этом месте. Впрочем это вопрос личных целей.SerafimArts
27.01.2017 13:30Начиная с года 2012го, когда я вернулся из фронт-энда обратно на бекенд — мне попадались проекты в которых не то что процедурного стиля, даже нарушений PSR не было. Покрытие тестами, согласен, все этим грешат, зачастую просто лень, работа сделана, всё работает, а дальше новые задачи. На последнем же месте работы коверейдж примерно 90%+, правда тесты функциональные, т.к. они более профитны для рефакторинга.
В любом случае наличие или отсутсвие тестов я могу принять, но подобную кодовую базу — нет, кажется что это какая-то фантастика из параллельных вселенных. Даже когда куда-то переходил и просто рассматривал какое-то место работы — всегда, если давали примеры кода, тем более примеры из реальных проектов — они были вполне вменяемыми и современными.
Единственное место на моей памяти, которое не соответсвовало этому критерию — это Кинопоиск. У них там древний php 5.3 и судя по вопросам на собеседовании — они мало стремятся это дело поправить, скорее искали разработчиков на поддержку. Так что рассматриваю это скорее как исключение, связанное с обширной неподдерживаемой кодовой базой.
http3
27.01.2017 15:14В больших компаниях большие и долгоживущие проекты. Я трижды попадал в такие и во всех случаях был самописный велосипед.
Хм, я постоянно говорю, что большие компании используют самопись, а не фреймворки.
Но получаю минусов. :)
Только некоторые уже сейчас пытаются следовать моде, создавая новые проекты.
lair
26.01.2017 18:54-1Только мне одному кажется сегодня чем-то диким заморачиваться на тему MVC и какой архитектуре/паттерну соответствует код?
Нет, не вам одному. Но людей, которым хорошая архитектура нужна, все еще достаточно.
akubintsev
26.01.2017 19:11+3Нужна — да. Но не стоит забывать, что все паттерны носят рекомендательный характер, а не обязательный, когда шаг влево/вправо — расстрел. Впрочем, на каком-то этапе может надо и построже, но я больше верю в целительную силу код ревью, поскольку второй задачей кода после выполнения им поставленной задачи является ясность для другого разработчика. А паттерны — один удобных из способов.
Удачность же архитектуры определяется способностью предвидеть изменения в проекте.lair
26.01.2017 19:13-1Вот чтобы у код-ревью была целительная сила, рано или поздно придется заморочитсья вопросом "какому паттерну соответствует этот код".
VolCh
28.01.2017 08:04Паттерны — это не более, чем общеупотребительные имена проверенных решений общих задач. Это даже не рекомендация решать эти задачи таким образом, это просто соглашение: такое-то решение такой-то задачи называется так-то. Именно для понятности другим разработчиком. Всё.
http3
27.01.2017 15:19Только мне одному кажется сегодня чем-то диким заморачиваться на тему MVC и какой архитектуре/паттерну соответствует код?
+1
Да и в повседневной разработке не нужно заново создавать MVC-каркас или использовать паттерны.
Пользуемся готовым функционалом, меняем в случае необходимости. Но не ради моды или галочки.
Fesor
28.01.2017 22:00+2Расслабьтесь и получайте удовольствие: в реальном мире нереальное количество говнокода.
Да, в этом и проблема. Его слишком много. У Роберта Мартина есть неплохая теория на этот счет. Количество разработчиков каждый 5 лет удваивается. Это значит что сегодня, завтра и через год в мире половина всех разработчиков будет иметь менее 5-ти лет опыта. Что это значит? Это значит что процент людей которые понимают что откуда и куда постоянно уменьшается.
Вместо того чтобы "учить людей MVC" попути спутав все понятия в одну кучу и забыв зачем вообще все это придумывалось (а ведь придумали MVC ажно 38 лет назад) следует больше внимания уделять таким вещам как декомпозиция, функциональная абстракция, принципы проектирования и т.д. Учить писать тесты (заметьте, не TDD а хотя бы тесты).
Чему и нужно учиться, так это как выживать среди всего этого бедлама, сводя к минимуму факапы и намазывая поверх код с новыми бизнес-фичами.
Тут опять же интересный момент. Если вам досталась приложенька реализующая логику посложнее банальных CRUD операций, где все размазано по контроллерам и вьюхам, то все будет сводиться к банальной рутине и тупому алгоритму:
- посадили на пару недель QA/разработчиков написать e2e тесты на основной функционал ну и попутно разобраться как все работает
- составили приоритизацию новых фич
- делаем дела постепенно переписывая функционал
И прикол тут в том что чтобы не погрузиться еще больше в ведерко с гуано нужно хорошо знать как делать правильно. Работа с легаси это посложнее чем работа с чистого листа (свой код не так пахнет как чужой).
akubintsev
30.01.2017 15:59Полностью согласен с тем, чему реально надо учить.
А вот достать дополнительно QA и тем более разработчиков — это далеко не всегда возможно. Ресурсов никто не даст просто так на рефакторинг, даже если обосновать математически выгоду в перспективе. В далекую перспективу неохотно верят, особенно в последние годы, нужны пруфы. Потратили столько денег — заработали на x% больше через год например.Fesor
30.01.2017 17:04А вот достать дополнительно QA и тем более разработчиков — это далеко не всегда возможно.
ну так это ж челендж для разработчика. Как с минимальными усилиями достич максимальной изоляции разработки и автоматизировать рутину на которую тратится время. Я не говорю о том что надо месяц или более чето там пилить, недельку достаточно для старта. Хотя конечно все сильно зависит от проекта, скоупа работ и команды.
Потратили столько денег — заработали на x% больше через год например.
тут тоже такой момент. Если ваш рефакторинг проекта окупится только через год — возможно вы взяли кусок непомерный. Возможно можно подумать еще, пойти на компромисы и почисть только ту часть кода которая принесет профит уже в течении месяца.
Например, у вас есть пул задач по проекту, и у вас есть регулярно пополняемый пул багов. Можно раз в недельку какую (в зависимости от того как часто обновляется пул и собирается статистика) тупо садиться и анализировать на что тратится время, в каких частях чаще вылазят баги, какого характера баги и т.д. Ну и от этого уже плясать, ибо фиксы таких проблем окупаются оооочень быстро.
Temirkhan
31.01.2017 17:22Стоимость разработки всегда растет. А наличие техдолга ускоряет ее рост. Вы не можете донести до бизнеса, что рефакторинг поможет заработать больше. Только то, что это снизит затраты и стоимость разработки.
VolCh
01.02.2017 06:41Если разрабатываемые фичи приносят деньги (а иначе зачем их разрабатывать? :) ), а рефакторинг ускоряет последующую разработку (тут сложнее, он может не ускорять, а, например, требовать для поддержки/развития специалистов меньшей квалификации), то рефакторинг приносит деньги напрямую. Грубо, есть пул задач на год вперёд с текущим графиком по фиче в месяц, каждая приносит по миллиону в месяц, а рефакторинг, на который требуется два месяца, сократит срок разработки каждой до трех недель. Без рефакторинга за год получим 66 миллионов, с рефакторингом задержим первое поступление на 2 месяца, через полгода догоним график по общей сумме дохода, а весь план выполним за 10 месяцев, заработав за год 68 миллионов, при условии что последних два месяца фич, приносящих деньги, делать не будем.
Temirkhan
01.02.2017 14:32Мы сделаем эту фичу за 4 недели, а следующая будет стоить уже 1 месяц. И так по нарастающей, если не займемся разрешением техдолга и тем самым не снизим дальнейшие расходы компании.
Мы сделаем рефакторинг за 2 месяца, а потом все фичи будут стоить 3 недели. Таким образом мы увеличим дальнейшие доходы компании.
На втором подносе присутствует ложь и она сыграет во вред тем, кто ведет разработку.
Fesor
01.02.2017 23:33то рефакторинг приносит деньги напрямую.
Есть нюанс. Для этого разработчик должен четко представлять в чем проблема и как ее исправить. Многие разработчики же просто хотят убрать то что им не нравится, и часто бывает так что с точки зрения бизнеса профита в этом нет.
В целом выделать время на рефакторинг так себе идея, а вот закладывать устранение тех долга в процесс разработки (скажем 20%) вполне себе норм.
VolCh
03.02.2017 06:35Часто бизнес настаивает на скорейшем запуске фич, типа оно уже работает — запускайте.
Fesor
03.02.2017 14:21ну как бы никто не мешает устранить критически важные проблемы для реализации фичи во время реализации фичи. В этом случае бизнес и фичу получит почти за то же время, и технический долг можно будет чуть снизить.
Разработчики любят рефакторить и улучшать свой код. Точно так же как оунеры любят генерить фичи которые не нужны. Ну то есть проблема одна и та же, плохая приоритизация, нет целей, нет таргет группы (или пула задач на ближайшее время или статистики по регрессиям чтобы оценить импакт технического долга в случае разработчиков)… Словом можно тратить намного меньше времени. Да, код не будет идеальным (как будто бы это возможно) но если поддерживать должный уровень изоляции то все будет относительно неплохо и дешево.
EmotionTigran
29.01.2017 11:45Сама по себе статья довольно слабая. Очень очень много информации не раскрывается. В любом случае, писать MVC самописку в 2017 году уже нету смысла. Если вас не устраивают full-stack большие фреймворки типа Symfony, Laravel, то скорее всего вам подойдут их микрофреймворки типа Silex
Fesor
29.01.2017 15:35+1Интересный факт, фреймворки вроде Symfony или Silex не являются MVC фреймворками (по сути сам термин MVC фреймворк это маркетинговый булшит который начался в 2004-ом году с появлением всяких RoR).
MetaDone
29.01.2017 17:46еще можно использовать тот же Symfony как микрофреймворк, или использовать Phalcon Micro Applications, или же собрать свое из компонентов
SmiteVils
29.01.2017 19:12-1А мне понравилась. Не знаю как уж с тех. сороны, но на пальцах хорошо обьяснил что такое MVC, я как новичек кажется понял. А если вы такие знающие, напишите пожалуйста статью для новичков, только правильную, и что бы понятно был, а то статей миллион и нихрена не понятно.
Fesor
29.01.2017 20:46+2Так и что такое модель? И что вы будете делать если у вас одна и так же логика будет требоваться в 2-х контроллерах?
EmotionTigran
30.01.2017 13:35Самое главное, что надо понять новичку — не надо писать свой MVC фреймворк. Над готовыми инструментами работает целая команда разработчиков и они скорее всего более опытные чем Вы.
VolCh
29.01.2017 20:50+1Также стоит упомянуть тот факт, что существует два лагеря: один пишет логику в контроллерах, второй в моделях.
А я как всегда ни рыба, ни мяса… Бизнес-логику пишу в модели (сущности, объекты-значения и сервисы в основном), логику приложения в контроллерах и инфраструктурных сервисах, а логику представления вообще в шаблонах.
lair
Э, серьезно? А аргументировать?
Это, на минуточку, называется Separated Presentation, и MVC — только один частный случай.
(и я даже не буду вдаваться в нюансы того, какие именно MVC бывают)
Смешно вы определились, да. А на основании чего? А то, что бывает доменная модель и доменные сервисы, вы не слышали?
Вообще, это называется "представление".
Откуда, стесняюсь спросить, вы взяли эту классификацию?
Ну и да, где полное описание паттерна-то? Что с чем взаимодействует, зачем, и все вот это вот?
Нее, понимания после вашего поста не будет, будет только еще одно "я тут написал что-то под названием MVC".
Old_Chroft
А касаемо самой статьи — объяснения по сути никакого, код на первый взгляд неплохой, за исключением парочки сомнительных мест:
index.php Какая такая причина пихать исходники в доступную из WWW директорию?
Ах, ну да, ну да.
Old_Chroft
Фу так делать.