Что такое рефакторинг и в чем его цели




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

34 Comments

  1. dandykry

    https://refactoring.guru/ru/refactoring/how-to — есть что-то общее с этим ресурсом

    Update: заметил, что ресурс указан в публикации

    Reply
  2. brr

    Мне кажется есть противоречие между уверждениями:

    в одной процедуре лучше избегать смешивания выполнения различных малосвязанных вещей

    и

    Безупречная функция сама должна определять контекст своей работы во время выполнения и извлекать из него необходимые параметры.

    Последнее утверждение вообще крайне спорно, представляю с какими сложностями можно столкнуться тестируя такую функцию.

    Reply
  3. Vladimir Litvinenko
    Reply
  4. check2
    Следующий пункт – отсутствие комментариев. Лично для меня это один из основных критериев того, что код хороший.

    Очень понятная процедура расчёт ебестоимости выпуска РАУЗ в УПП. Там практически нет комментариев, но от их отсутствия она не становится понятнее. Скажем так, критерий отсутствия комментариев условие необходимое для хорошести кода но далеко не достаточное, и оценивать качество кода по отсутствию комментариев в нём я бы не стал.

    Reply
  5. ArchLord42

    (4)

    Очень понятная процедура расчёт ебестоимости выпуска РАУЗ в УПП. Там практически нет комментариев, но от их отсутствия она не становится понятнее.

    Данная статья выжимка из некоторых книг стайте про чистый код и тд.

    И я подозреваю автор имел ввиду то, что собственно в них и написано.

    Смысл весь в том, что в идеале код не должен содержать комментарии, т.е. он должен быть самодокументированным.

    Если вы пишите что-то и у вас появляются сомнения, что через пару дней вы и сами не поймете «без бутылки», что этот код делает, а время на рефакторинг нет, то лучшим решением конечно будет написание комментариев, ибо только хороший код (с точки зрения читаемости) без комментариев является хорошим.

    Reply
  6. dm_romanov.idm

    (4)

    ИМХО, суть этого пункта в следующем: код должен быть читаем без комментариев.

    Если нужны комментарии в коде, значит что-то не то с кодом. Код не достаточно декомпозирован или названия переменных и функций в коде не отражают их назначения.

    Сложную функцию, которая не пойми-что вычисляет, лучше разбить на маленькие функции с понятными названиями.

    Сложное условие вынести в отдельную функцию с понятным названием.

    и т. д.

    Исключение тут сложные алгоритмы как расчет себестоимости, но их тоже лучше описывать не комментариями в коде, а в отдельных документах с диаграммами.

    Reply
  7. HAMMER_59

    Крайне спорное утверждение: «Нужно стремиться к минимизации кода».

    Более того при применении декомпозиции, кода становится не меньше, а больше. Другое дело, что в рамках одной процедуры или функции, кода становится действительно меньше, кроме того и переменных становится меньше в рамках функции либо процедуры.

    А вот к минимизации стандартов для написания когда, вот к этому точно стремится, т.к. подразумевается что их нужно применять регулярно и держать все это в голове.

    Reply
  8. HAMMER_59

    (6) По-моему, полный бред, что код должен быть без комментариев.

    Конечно, может появиться иллюзия, что код итак отлично читается. Но это пока находишься в нужном контексте, а когда вернешься к коду через полгода, вот тогда и придет понимание, что не так уж все и однозначно.

    Reply
  9. dm_romanov.idm

    (8)

    Не буду спорить. Скажу лишь о двух больших минусах комментариев:

    1. Комментарии имеют свойство устаревать, зачастую их не обновляют при изменении кода, в результате комментарий становится бесполезным или даже вредит, направляя мысль разработчика в противоположную сторону.

    2. Комментарии не имеют ценности для бизнеса и пользователей, не привносят в создаваемый продукт новой функциональности.

    ИМХО поэтому проще и выгоднее писать и обновлять читаемый код, чем писать и обновлять комментарии.

    Reply
  10. АлександрЯрославичъ

    Спасибо за статью

    Reply
  11. kosmo0

    (9) Как всегда, слово комментарии разные люди понимают с некоторыми отличиями.

    Есть комментарии которые пишутся в стиле «банальные вещи». А есть комментарии которые указывают на некоторые нюансы.

    Например в коде прописано какая-то «лишняя» проверка. И при рефакторинге возникнет дикое желание убрать ее. Либо сидеть и лопатить код в целях понимания ради чего эта проверка. А эта проверка срабатывает в одном случае из 1000 и если пропустить этот случай, то потом полбухгалтерии будет искать причину своей проблемы. И для полного счастья будет этот код в общем модуле куда тыкается полконфигурации.

    Другой момент. Это когда комментарии касаются предметной области. То есть, если вы полностью понимаете предметную область — это одно, иначе без комментариев потенциально увеличение времени понимания кода.

    Reply
  12. AlexGroovy

    Краткий смысл всей статьи -«Harder,better,faster,stronger»

    Reply
  13. MikhailDr

    Я думал комментарий нужен не столько для того, чтобы можно было понять о чем код, сколько для того, чтобы ускорить этот процесс. Т.е. маленький комментарий «Расчет скидки для прайсовой цены» ты прочитаешь гораздо быстрее, чем самый грамотно написанный код расчета этой скидки.

    Reply
  14. spacecraft

    (13)

    Т.е. маленький комментарий «Расчет скидки для прайсовой цены» ты прочитаешь гораздо быстрее, чем самый грамотно написанный код расчета этой скидки.

    Если в коде необходим такой комментарий, то это первый признак необходимости рефакторинга этого кода: вынос этого участка кода в отдельный метод с соответствующим именем.

    Reply
  15. dm_romanov.idm

    (11)

    Я против фанатизма и комментарии действительно бывают нужны, когда они помогают разработчикам разобраться в коде, как в случае с «лишней» проверкой.

    Но предметную область описывать в комментариях это ИМХО не правильно, лучше описывать в проектных документах, вики и т.п..

    Reply
  16. dm_romanov.idm

    (13)

    Процедура или функция «РасчетСкидкиДляПрайсовойЦены» читается не хуже.

    Reply
  17. MikhailDr

    (14) Хорошо, неудачный пример. Вот из последнего, у бухгалтерии не выводились в печатной форме авансового отчета должность и подразделение физического лица. Залез в код, на формирование печатной формы работает масса процедур и функций и вот например

    // Возвращает таблицу значений содержащую поля ФизическоеЛицо и Сотрудник. Сотрудник отбирается по принципам:

    // — Работает на указанный период.

    // — Выбирается сотрудник, работающий по основному месту работы, если такового не существует, выбирается

    // сотрудник, работающий по совместительству, принятый на наиболее раннюю дату.

    //

    // Параметры:

    // СписокФизическихЛиц — Массив ссылок на элементы справочника ФизическиеЛица или

    // — СправочникСсылка.ФизическиеЛица

    // — Неопределено — в таблицу войдут «основные» сотрудники всех

    // физических лиц когда либо работавших в организации.

    // ТолькоРазрешенные — Булево

    // Организация — СправочникСсылка.Организации

    // Период — Дата

    //

    //

    // Возвращаемое значение:

    // ТаблицаЗначений — Таблица значений, содержащая поля Сотрудник и соответствующее сотруднику ФизическоеЛицо.

    //

    Функция ОсновныеСотрудникиФизическихЛиц(СписокФизическихЛиц, ТолькоРазрешенные, Организация, Период) Экспорт

    В принципе я бы смог дальше пойти по цепочке функций и понять что она возвращает и по каким принципам, но ведь проще и главное быстрее сделать это по комментарию. Еще важно понимать какой тип у передаваемых параметров, несмотря на то, что это можно выяснить в отладчике. А еще в комментарии можно прописать условия расчета, как в этом примере указано, что если сотрудника по основному месту работы нет, то выбирается сотрудник, работающий по совместительству.

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

    Reply
  18. spacecraft

    (17) тут нужно разделить понятия: комментирование кода и комментарий метода. Последний нужен. Он нужен в первую очередь, как документация. Он не расписывает сам код.

    Reply
  19. MikhailDr

    (18) Но в статье то все категорично

    Следующий пункт – отсутствие комментариев. Лично для меня это один из основных критериев того, что код хороший. А так я с вашим тезисом согласен

    Reply
  20. spacecraft

    (19) далее же описано: «Если код требуется комментировать, это плохой код». В (17) приведен комментарий не кода, а описание интерфейса ( не путать с UI — пользовательский интерфейс).

    Возможно в статье это неявно выражено, но понимается это именно так.

    Reply
  21. spacecraft

    (19) да, есть еще направление, которое не приемлет вообще никакого комментария. В том числе и описания методов. Это «экстремальное программирование», основанное на TDD. Но там «комментариями»» служат тесты. К 1С это нормально применить практически невозможно.

    В любом случае все сходятся к тому, что внутри метода комментарии излишни.

    Reply
  22. _LkMaksimka_

    Комментарий нужен краткий который позволяет понять, что делает функция(процедура) и что возвращает функция. А комментарии, которые описывают каждую строку функции или процедуры, не нужны.

    Reply
  23. vadim1011985

    У всех свое понятия комментария лично я понял это так : не нужно комментировать что делает код построчно например :

    Для каждого книга из библиотеки Цикл // перебираем книги в библиотеке
    
    // переместим все книги из одного помещения в другое
    …..
    …..
    …..
    
    КонецЦикла 

    т.е. код должен быть читаемым без всяких комментариев.

    Но комментарии нужны для описания общих действий например

    кусочек кода из типовой БП

    Процедура СформироватьДвиженияПереоценкаВалютныхОстатков(ТаблицаВалютныхОстатков, ТаблицаРеквизиты, Движения, Отказ) Экспорт
    
    Если Не ЗначениеЗаполнено(ТаблицаРеквизиты)
    Или Не ЗначениеЗаполнено(ТаблицаВалютныхОстатков) Тогда
    Возврат;
    КонецЕсли;
    
    Параметры = ПодготовитьПараметрыПереоценкаВалютныхОстатков(ТаблицаВалютныхОстатков, ТаблицаРеквизиты);
    Реквизиты = Параметры.Реквизиты[0];
    
    Дата              = Реквизиты.Период;
    Организация       = Реквизиты.Организация;
    
    ТаблицаПереоценка = Параметры.ТаблицаПереоценка;
    Проводки        = Движения.Хозрасчетный;
    
    // С целью оптимизации производительности напрямую (а не через функции с повторно используемыми значениями) кешируем
    // свойства счетов. При заполнении субконто исключаем лишние проверки на значения субконто (наличие субконто на счете
    // и т.п. существующие в алгоритме как предусловия).
    СчетаПереоценкиКеш = Новый Соответствие;

    Показать

    Reply
  24. spacecraft

    (23) вот как раз второй кусок кода яркий пример «нехорошего кода».

    1. комментарий внутри метода не читаем. Не все его вообще прочитают. При свернутом методе так точно.

    2. Метод сложный. В нем наворочено много разнородных действий.

    Этот кусок кода явно нуждается в рефакторинге. Несвязанные действия с прямым назначением метода необходимо выделить в отдельные методы.

    Reply
  25. vadim1011985

    (24) Я просто показал пример , на счет нечитаемости — по-моему это чисто субъективно , для меня он нормально читаем , если надо разобраться как работает функция вы ее все-же разворачиваете (это про свертываемость) На счет сложности — опять же чисто субъективно , но спорить не буду.

    Reply
  26. spacecraft

    (25)

    на счет нечитаемости — по-моему это чисто субъективно , для меня он нормально читаем , если надо разобраться как работает функция вы ее все-же разворачиваете (это про свертываемость)

    Смотрим. Функция экспортная, значит это интерфейсная функция. Если по названию и описанию к функции невозможно понять, что она делает и нужно разворачивать функцию и изучать код, значит что-то не то с самой функцией.

    Если в интерфейсной функции много действий, которые еще и отдельно комментировать нужно… это вообще атас.

    Reply
  27. vadim1011985
    Reply
  28. spacecraft

    (27) Если метод помечен как экспортный, то он по определению становится интерфейсным данного модуля. К нему могут обращаться извне.

    Что делает конкретный служебный метод, для пользователя интерфейса не важно.

    В данном случае, если требуется отладка служебного метода, значит этот код не может быть хороший, если только не сами его пишите.

    вопрос — если бы не было комментария смогли бы вы определить какой тип надо поставлять в данный параметр ?

    Если необходимо извне узнавать тип передаваемого параметра из комментария внутри служебного метода… это точно нехороший код.

    Поймите, нехороший код это не означает нерабочий код, или что он работает медленнее. Это означает, что этот код можно рефакторить.

    Reply
  29. dm_romanov.idm

    (27)

    Здесь можно было использовать структуру вместо строки и вместо комментария задавать тип значения в коде. Читаемость была бы не хуже, всё равно внутри метода он переводит в структуру.

    К сожалению, 1С достаточно бедный язык, там где разработчики указывают тип в комментарии в других языках указывают тип в коде. Что служит и защитой от неверно переданных параметров и помогает автодополнению.

    Reply
  30. Leits

    спасибо за статью!

    Reply
  31. alexsey777

    (7)Согласен. Постоянно рефакторю свой код. В основном в сторону декомпозиции. Чтобы 1 метод выполнял конкретное действие, которое можно определить из названия метода.

    В этом случае когда становится больше, но его гибкость и понятность увеличивается.

    Reply
  32. rpgshnik

    С комментарием не согласен. Хорошо когда и код легко читаемый и комментарий хороший.

    Про параметры тоже не согласен. Бывают случаи когда да необходимо указать с десяток параметров. Частные но необходимые случаи.

    В остальном об этом уже и здесь и везде писали не однократно. Вот только красивый код это как искусство, кому-то дано, кому-то нет. Дано увы малому проценту и если из этого процента состоит ваша команда то круто!

    Reply
  33. check2

    (6)

    Исключение тут сложные алгоритмы как расчет себестоимости, но их тоже лучше описывать не комментариями в коде, а в отдельных документах с диаграммами.

    Об этом и речь, что не нужно всё под одну гребёнку.

    Reply
  34. AlexCherdakov

    со всем согласен главное не переусердствовать, например стремление к «минимуму строк кода» без оглядки на его читаемость, полный отказ от комментирования кода и т.п. Короче стремление к «хорошести» кода ради самой «хорошести» это классическая подмена ценностей…

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *