Приклад
Я натрапив на монолітний код, який робить "все" в одному місці - завантажуючи дані з бази даних, показуючи розмітку HTML, виконуючи роль маршрутизатора / контролера / дії. Я почав застосовувати код баз даних SRP, що рухається, до власного файлу, забезпечуючи кращу назву речей, і все це виглядало добре, але потім у мене виникли сумніви, чому я це роблю.
Чому рефактор? Яка мета? Це марно? Яка користь? Зауважте, що я здебільшого залишив монолітний файл таким, яким він є, але відновив лише меншу частину, що стосувалася області, де мені потрібно було виконати певну роботу.
Оригінальний код:
Щоб навести конкретний приклад, я натрапив на цей фрагмент коду - він завантажує специфікації продукту або за відомим ідентифікатором продукту, або за обраним користувачем ідентифікатором версії:
if ($verid)
$sql1 = "SELECT * FROM product_spec WHERE id = " . clean_input($verid);
else
$sql1 = "SELECT * FROM product_spec WHERE product_id = " . clean_input($productid) ;
$result1 = query($sql1);
$row1 = fetch_array($result1);
/* html markup follows */
Реконструкція:
Оскільки я виконую деяку роботу, яка вимагає від мене змінити речі в цій конкретній частині коду, я змінив її для використання шаблону репозиторію та оновив його до використання об'єктно-орієнтованих засобів MySQL:
//some implementation details omitted
$this->repository = new SpecRepository($mysql);
if ($verid)
$row1 = $this->repository->getSpecByVersion($verid);
else
$row1 = $this->repository->getSpecByProductId($productid);
/* html markup follows to be refactored or left alone till another time*/
//added new class:
class SpecRepository extends MySqlRepository
{
function getSpecByVersion(int $verid)
{
return $this->getMySql()->paramQuery("
SELECT * FROM product_spec WHERE id = ?
", $verid)->getSingleArray();
}
function getSpecByProductId(int $productid)
{
return $this->getMySql()->paramQuery("
SELECT * FROM product_spec WHERE product_id = ?
", $productid)->getSingleArray();
}
}
Чи варто це робити?
Озираючись на зміни, код все ще є, код з однаковою функціональністю, але в різних файлах, різних назвах, місцях, використовуючи більше об'єктно-орієнтований стиль, а не процедурний. Насправді смішно відзначити, що відреставрований код виглядає набагато більш роздутим, незважаючи на той самий функціонал.
Я передбачаю кілька відповідей, які говорять "якщо ви не знаєте причин, через які ви робите рефактор, не робіть цього", і, можливо, я можу погодитися. Мої причини полягають у покращенні якості коду з часом (і я сподіваюся, що я це зроблю, дотримуючись SRP та інших принципів).
Це досить вагомі причини чи я витрачаю час на "перестановку коду" таким чином? Загалом рефакторинг - це трохи схоже на те, що я бродячи водою, якщо чесно - це потребує часу, і воно стає більш "відокремленим", наскільки йде СРП, але, незважаючи на мої добрі наміри, я не відчуваю, що я встигаю зробити дивовижні поліпшення. Отже, дискусія про те, чи найкраще залишати код як раніше, а не рефактор.
Чому я в першу чергу рефактор?
У моєму випадку я додаю нову функціональність для нової лінійки продуктів, тому мені доведеться або слідувати існуючій структурі коду для подібних ліній продуктів, або писати власну.
select *
стає "найкращою практикою".
Select * from ..
можна вважати анти-закономірністю. Дивіться stackoverflow.com/q/3639861/31326