Рефакторинг без тормозов (десять приемов в одной задаче)

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

Функция, используемая для примера, решает задачу разбиения периода времени, заданного начальной и конечной датой, на отрезки, принадлежащие различным месяцам. Пусть в исходном варианте вид функции будет таким —ВАРИАНТ0:

Функция РазбитьПериод0(ДатаС, ДатаПо) Экспорт
МассивПериодов = Новый Массив;
Дата1 = ДатаС;
Дата2 = ДобавитьМесяц(НачалоМесяца(Дата1), 1);
Пока Истина Цикл
Дата3 = Дата2 - 1;
Если Дата3 > ДатаПо Тогда
Дата3 = ДатаПо
КонецЕсли;
ЗаписьПериода = Новый Структура;
ЗаписьПериода.Вставить("НачалоПериода", Дата1);
ЗаписьПериода.Вставить("КонецПериода", Дата3);
МассивПериодов.Добавить(ЗаписьПериода);
Если Дата3 = ДатаПо Тогда
Прервать
КонецЕсли;
Дата1 = Дата2;
Дата2 = ДобавитьМесяц(Дата1, 1)
КонецЦикла;
Возврат МассивПериодов
КонецФункции

Здесь можно сделать следующее

  1. Можно не выполнять присваивания «Дата1 = ДатаС». Вместо этого достаточно использовать сам параметр «ДатаС» как переменную, а чтобы после выполнения функции его значение не оказалось «испорченным», перед ним в заголовке функции нужно использовать лексему «Знач». Это означает, что параметр передается не «по ссылке», когда используется ранее выделенная переменной память, а «по значению», когда создается новый экземпляр переменной.

  2. Можно сэкономить на придумывании осмысленного названия переменной, предназначенной для вычисляемого значения функции. Если результат функции строится в ходе ее выполнения и должен быть как-то заранее назван, лучше не выдумывать нового термина, так как у функции уже есть имя, а назвать результат выполнения функции в процессе его вычисления просто «Результат» или «Ответ».

  3. Последовательность операторов «Дата3 = Дата2 — 1;Если Дата3 > ДатаПо Тогда Дата3 = ДатаПо КонецЕсли» это всего лишь присвоение значения переменной «Дата3» с учетом ограничения ее значения сверху значением переменной «ДатаПо». Эта задача проще и нагляднее решается с помощью функции «Мин». То есть, если результат выражения должен учесть ограничения на результат сверху или снизу, следует использовать функцию  минимум или максимум, которые читаются легче и пишутся короче, чем условный оператор «если» или условный оператор с вопросом.

  4. Конструктор структуры позволяет сразу проинициализировать ее элементы, поэтому вставку элементов можно сократить. Для создания структуры и инициализации ее полей можно пользоваться соответствующей формой конструктора, куда сразу передать имена полей через запятую и значения полей. Так создаются структуры периодов, добавляемых в массив.

  5. Можно не создавать переменную для ссылки на создаваемую структуру. Так как она будет использована лишь однажды – в следующей строке программы. Вместо этого результат можно сразу записать на место его использования. Тогда не нужно будет «вымучивать» названия лишних переменных. Исключением являются случаи, когда промежуточный результат требует пояснения или контроля в процессе отладки. В нашем случае строка и без этого легко читается: в массив-результат добавляется новая структура из полей «НачалоПериода», «КонецПериода», имеющих соответствующие значения.

В результате функция оказывается приведенной к виду ВАРИАНТ1:

Функция РазбитьПериод1(Знач ДатаС, ДатаПо) Экспорт
Ответ = Новый Массив;
Дата2 = ДобавитьМесяц(НачалоМесяца(ДатаС), 1);
Пока Истина Цикл
Дата3 = Мин(Дата2 - 1, ДатаПо);
Ответ.Добавить(Новый Структура("НачалоПериода, КонецПериода", ДатаС, Дата3));
Если Дата3 = ДатаПо Тогда
Прервать
КонецЕсли;
ДатаС = Дата2;
Дата2 = ДобавитьМесяц(ДатаС, 1)
КонецЦикла;
Возврат Ответ
КонецФункции

Анализируя эту запись, можно придти к выводу, что переменные «ДатаС», «Дата2» и «Дата3» связаны простой зависимостью. «ДатаС» – это начало периода или начало текущего месяца, «Дата2» – это начало следующего, а «Дата3» – конец текущего месяца. Выполним подстановку и

  1. Избавимся от лишних, то есть связанных простой зависимостью, переменных.

В результате этого получаем ВАРИАНТ2:

Функция РазбитьПериод2(Знач ДатаС, ДатаПо) Экспорт
Ответ = Новый Массив;
Пока ДатаС < = ДатаПо Цикл
Ответ.Добавить(Новый Структура("НачалоПериода, КонецПериода", ДатаС, Мин(КонецМесяца(ДатаС), ДатаПо)));
ДатаС = КонецМесяца(ДатаС) + 1
КонецЦикла;
Возврат Ответ
КонецФункции

Внимание: Из-за того, что знак «меньше или равно» в тексте функции неправильно отрабатывается при редактировании статьи на этом сайте, в него добавлен пробел!

Похожий вариант уже публиковался на Инфостарте [?], вот он — ВАРИАНТ3:

Функция РазбитьПериод3(ДатаС, ДатаПО) Экспорт
Ответ=Новый Массив;
Мес=НачалоМесяца(ДатаС);
Пока Мес< =НачалоМесяца(ДатаПО) Цикл
Период=Новый Структура;
Период.Вставить("НачалоПериода", ?(НачалоМесяца(ДатаС)=Мес,ДатаС,Мес));
Период.Вставить("КонецПериода", ?(НачалоМесяца(ДатаПО)=Мес,ДатаПО,КонецМесяца(Мес)));
Ответ.Добавить(Период);
Мес=ДобавитьМесяц(Мес,1);
КонецЦикла;
Возврат Ответ;
КонецФункции

Здесь само собой напрашивается применение приемов 3, 4 и 5, в результате чего получается более красивый и компактный ВАРИАНТ4 

Функция РазбитьПериод4(ДатаС, ДатаПО) Экспорт
Ответ = Новый Массив;
Мес = НачалоМесяца(ДатаС);
Пока Мес < = ДатаПО Цикл
Ответ.Добавить(Новый Структура("НачалоПериода, КонецПериода", Макс(ДатаС,Мес), Мин(ДатаПО,КонецМесяца(Мес))));
Мес = ДобавитьМесяц(Мес, 1)
КонецЦикла;
Возврат Ответ
КонецФункции

В общем, результат в варианте 2 уже можно было бы принять, однако функция «Мин» смотрится инородно. Возможно, это от того, что она срабатывает лишь однажды – на самом последнем периоде. И если периодов много – эти сравнения оказываются лишними. Также, кажется, что можно избавиться от переменной «ДатаС», которая всегда на единицу больше конца периода, только что записанного в массив. А если попробовать сначала записать в массив исходный интервал, а затем при необходимости делить его на две записи, выделяя последний месяц в следующую запись? Алгоритм уместился в одном предложении. Возможно, и его запись окажется понятнее и проще?

Чтобы при этом не приходилось затем удалять записи, если интервал «отрицательный», выполним в этом случае обмен «ДатаС» и «ДатаПо». Здесь повторим прием 3 и обойдемся без условных операторов: началом периода будем считать минимум, а концом – максимум значений этих переменных. С точки зрения пользователя функции, это будет удобнее: программисту при записи вызова функции не нужно будет помнить, какую дату записывать первой – меньшую или большую, период можно будет задать и так и так. Функция станет более «робастной», то есть станет лучше защищена от ошибок в исходных данных. Конечно, это будет иметь свою цену — так отсекается возможность использования функции для контроля, что «ДатаС» меньше «ДатаПо». В результате получаем следующий ВАРИАНТ5:

Функция РазбитьПериод5(ДатаС, ДатаПо) Экспорт
Ответ = Новый Массив;
Ответ.Добавить(Новый Структура("НачалоПериода, КонецПериода", Мин(ДатаС, ДатаПо), Макс(ДатаС, ДатаПо)));
Пока НачалоМесяца(Ответ[0]["НачалоПериода"]) < НачалоМесяца(Ответ[0]["КонецПериода"]) Цикл
Ответ.Вставить(1, Новый Структура("НачалоПериода, КонецПериода", НачалоМесяца(Ответ[0]["КонецПериода"]), Ответ[0]["КонецПериода"]));
Ответ[0]["КонецПериода"] = Ответ[1]["НачалоПериода"] - 1
КонецЦикла;
Возврат Ответ
КонецФункции

Рассматривая этот результат, можно заметить, что текст «НачалоПериода», «КонецПериода», «Ответ[0]» часто повторяется. Поэтому,

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

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

Прием 8 заслуживает демонстрации еще одним примером. Вот функция для получения количества элементов массива, равных образцу, с использованием приема 8.

Функция Сколько(Массив, Образец, Ответ = 0) Экспорт
Для Каждого Элемент Из Массив Цикл
Ответ = Ответ + Число(Элемент = Образец)
КонецЦикла;
Возврат Ответ
КонецФункции

Если массив «Слова» хранит слова программного кода некоторой функции, то выражение

    Сколько(Слова, «Цикл», Сколько(Слова, «Тогда», 1))

рассчитает показатель цикломатической сложности функции.

Возвращаясь к исходной функции, применение приемов 7 и 8 дает следующий результат — ВАРИАНТ6:

Функция РазбитьПериод6(ДатаС, ДатаПо, Поле1 = "НачалоПериода", Поле2 = "КонецПериода") Экспорт
Ответ = Новый Массив;
Э = Новый Структура(Поле1 + "," + Поле2, Мин(ДатаС, ДатаПо), Макс(ДатаС, ДатаПо));
Ответ.Добавить(Э);
Пока НачалоМесяца(Э[Поле1]) < НачалоМесяца(Э[Поле2]) Цикл
Ответ.Вставить(1, Новый Структура(Поле1 + "," + Поле2, НачалоМесяца(Э[Поле2]), Э[Поле2]));
Э[Поле2] = Ответ[1][Поле1] - 1
КонецЦикла;
Возврат Ответ
КонецФункции

Рассматривая текущий вариант функции, можно заметить повтор в четырех местах названия функции «НачалоМесяца». Если это название разделить на два слова и сделать второе из них параметром функции, то она станет более универсальной, сможет выполнять разбивку на «Минуты», «Часа», «Дни», «Недели», «Месяца», «Квартала», «Года» (по понятным причинам придется смириться с некоторым диссонансом в произношении названий периодов). Для этого нам понадобится функция «Выполнить», которая воспринимает код как строку и выполняет его. В исходном коде название функции заменяется на «_», то есть «впишите что хотите», а перед выполнением туда вписывается нужный интервал заменой подстроки. В данном случае применяется наиболее спорный, ухудшающий понимание программы, прием

  1. Универсализации кода с использованием оператора «Выполнить». Этот прием следует применять с осторожностью.

Получаем следующий ВАРИАНТ7:

 
Функция РазбитьПериод7(ДатаС, ДатаПо, НаЧто = "Месяца", Поле1 = "НачалоПериода", Поле2 = "КонецПериода") Экспорт
М = Новый Массив;
Э = Новый Структура(Поле1 + "," + Поле2, Мин(ДатаС, ДатаПо), Макс(ДатаС, ДатаПо));
М.Добавить(Э);
Выполнить(СтрЗаменить(
"Пока _(Э[Поле1])< _(Э[Поле2])Цикл М.Вставить(1,Новый Структура(Поле1+"",""+Поле2,_(Э[Поле2]),Э[Поле2]));Э[Поле2]=М[1][Поле1]-1 КонецЦикла"
, "_", "Начало" + НаЧто));
Возврат М
КонецФункции

Переменная «Ответ» заменена однобуквенной переменной «М» для сокращения длины строковой константы, содержащей шаблонизированный код.

Оглядев результат, видим, что в последнем варианте совершенно потеряна простота и понятность кода, которая ранее оправдывала менее компактную запись функции в варианте 5. Поэтому вернемся к варианту 2 и применим к нему приемы 7, 8 и 9. Здесь мы используем прием

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

В итоге получили следующую универсальную функцию, решающую поставленную задачу (знак «_» заменен словом «Край», что обеспечивает читабельность функции внутри строки ), ВАРИАНТ8:

 
Функция РазбитьПериод8(Знач А, Б, Чего = "Месяца", Поля = "НачалоПериода, КонецПериода") Экспорт
М = Новый Массив;
Выполнить(СтрЗаменить("Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла", "Край", "Конец" + Чего));
Возврат М
КонецФункции


Можно предложить еще дальше и переписать функцию на английский. Получим последний, десятый ВАРИАНТ9

 

Function РазбитьПериод9(Val A, B, What = "Месяца", Fields = "НачалоПериода, КонецПериода") Export
M = New Array;
Execute(StrReplace("While A<=B Do M.Add(New Structure(Fields,A,Min(Edge(A),B)));A=Edge(A)+1 EndDo", "Edge", "Конец" + What));
Return M
EndFunction

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

Нужно сказать, что улучшение кода – процесс, результат которого не всегда можно оценить однозначно. Объективная составляющая оценок представлена метриками кода. Значения метрик компактности и цикломатической сложности [Анализ цикломатической сложности кода] для всех промежуточных вариантов рассматриваемой функции приведены в таблице.

Номер варианта Число строк Число знаков Цикломатическая сложность Произвольный период
0 21 494 4 Нет
1 14 348 3 Нет
2 8 255 2 Нет
3 12 385 4 Нет
4 9 279 2 Нет
5 9 469 2 Нет
6 10 399 2 Нет
7 9 407 1 Да
8 5 263 1 Да
9 5 242 1 Yes!

Субъективная составляющая оценок отражает простоту и понятность кода. Применяя все перечисленные приемы исключительно в погоне за компактностью, можно пропустить момент утраты понятности кода, то есть важно вовремя затормозить. Но когда? Наверное, каждый должен решать сам. В конце концов, кто-то считает, что «тормоза придумали трусы», а кто-то: «тише едешь – дальше будешь».

52 Comments

  1. ivanov660

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

    Reply
  2. mymyka

    Рефа́кторинг (англ. refactoring) или реорганизация кода — процесс изменения внутренней структуры программы, не затрагивающий её внешнего поведения и имеющий целью облегчить понимание её работы.

    Экономия букв/строк в коде — не есть рефакторинг.

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

    (1)

    в типовых решениях не всегда увидишь подобного подхода

    И слава богу.

    Reply
  3. ManyakRus

    (2) mymyka,

    mymyka прав 🙂

    а автор вредитель 🙂

    Reply
  4. ildarovich

    (3) Я не вредитель, я — перфекционист — со времен программирования на Ассемблере не люблю избыточность в коде. Ну а Вы свою позицию обозначили, я ее упоминул в статье: «тише едешь — дальше будешь».

    Reply
  5. ildarovich

    (2) Знаете, мне более близко определение из английской Википедии

    Code refactoring is a «disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior», undertaken in order to improve some of the nonfunctional attributes of the software. Advantages include improved code readability and reduced complexity to improve the maintainability of the source code, as well as a more expressive internal architecture or object model to improve extensibility.

    В нем НИЧЕГО НЕ ГОВОРИТСЯ об облегчении понимания программы. Рефакторинг — это любое улучшение качества кода, борьба за его чистоту. Как говорил Экзюпери

    В любом деле совершенство достигается не тогда,когда больше нечего добавить, а тогда, когда больше нечего отнять

    В моем понимании чистота кода — это отсутствие необоснованной избыточности. Все приемы,перечисленные в статье (за исключением 9-го, который готов отстаивать отдельно), это классические приемы рефакторинга, перечисленные и в русской Википедии тоже.

    Так что не прячтесь за цитированием вырванных из контекста отрывков из Википедии, а объясните толком, конкретно, чем Вам не нравится вариант 2, например, или вариант 5. Или с каким приемам из 1-10 Вы не согласны.

    Reply
  6. mymyka

    (5)Избыточность кода никак не влияет на работу программы. Время исполнения отличается на микросекунды.

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

    Не забывайте, мы все таки пишем бизнес-приложение, а не компилированный экземпляр ускоспециализированной программы. Если бизнес-приложение не развивается, это значит, что оно не используется.

    Функция РазбитьПериод8(Знач А, Б, НаЧто = «Месяца», Поля = «НачалоПериода, КонецПериода») Экспорт
    М = Новый Массив;
    Выполнить(СтрЗаменить(«Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(_(А),Б)));А=_(А)+1 КонецЦикла», «_», «Конец» + НаЧто));
    Возврат М
    КонецФункции
    

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

    Перфекционизм это хорошо, особенно, когда за него платит заказчик.

    Reply
  7. ildarovich

    (6) Избыточность в коде — это мусор. Скажете, что мусор в лесу никак Вам мешает? Мусор в коде отвлекает наше внимание, забирает место на дисках, такты процессора, а в конечном счете — электроэнергию. Мусор в коде снижает его надежность, затрудняет внесение в него изменений.

    Впрочем, на эту тему уже исписаны груды бумаги. Вот, например: «Раньше я думал, что системы становятся более гибкими благодаря тому, что в них добавляется новый код. Однако сейчас я пришел к выводу, что системы становятся более гибкими потому, что из них удаляют лишний код. Пространство вокруг кода обладает значительно большим потенциалом, чем сам код» (Майкл Федерс). «Добавить код в систему значительно проще, чем убрать оттуда код. Рефакторинг позволяет делать вам код настолько простым, насколько это возможно, благодаря этому вы можете сконцентрироваться на добавлении в код новых возможностей» (Кен Ауэр, Рой Миллер).

    А Вы сами практикуете рефакторинг? Как Вы это делаете? Приведите пример хорошо отрефакторенной, с Вашей точки зрения функции!

    Вы прицепились к приемы 9, который является, в некотором смысле, «провокацией», оправдывающей «отвязное» название статьи. Я отчасти соглашусь с Вами и заменю знак «_» в теле строки на нечто более осмысленное, например «Край». Тогда, на мой взгляд строка

    «Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла»

    будет вполне читаемой.

    Любой рефакторинг увеличивает время разработки. Выигрыш получается потом.

    Читабельность(забудьте на секунду про прием 9 — он исключение) я стараюсь не ухудшать.

    Данная функция является готовым законченным решением. Она не требует внесения изменений внутри нее. Выходные и праздничные дни нужно исключать не «соединяя ужа с ежом» (такого бреда в 1С предостаточно), а постобработкой полученных на первом этапе периодов (подкинули отличную идею — обязательно покажу как это максимально просто сделать!), то есть еще важно правильно структурировать код.

    Как раз для будущего развития мы и убираем постоянно мусор в коде, чтобы не спотыкаться о него впоследствии.

    Reply
  8. mymyka
    Reply
  9. ildarovich

    (8) Ага!

    Очень жадная девочка пошла выбрасывать мусор, а вернулась с двумя пакетами

    Код, устойчивый к ошибкам — это и есть мой код. Чем меньше код, тем меньше вероятность ошибки (могу доказать математически). Где легче найти ошибку: в 254 знаках или в 500? Кстати, поверьте, такой код практически не приходится отлаживать (вариант 5-7), поскольку в него сразу встроены необходимые проверки.

    Посмотрел Ваш код. Выводы: «… и эти люди запрещают мне ковырять в носу!».

    Для читабельности не хватает отступов.

    Обязательно выделите в отдельные функции или процедуры часто используемые фрагменты кода. Сможете их использовать повторно (сэкономите деньги заказчика или свою прибыль повысите), а размер основной функции должен укладываться в страницу.

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

    Для примера посмотрите код УТ11 — он достаточно красив, на него можно равняться.

    Reply
  10. Yashazz

    К сожалению, солидарен с Ильдаровичем. К сожалению потому, что иногда чрезмерно увлекаюсь означенным рефакторингом, вплоть до чистого эргономо-эстетства и оптимизации, когда сие уже не особенно требуется. Время иногда трачу слишком. Силы трачу несоразмерно. Перфекционизм, как он есть. 🙂

    Reply
  11. Гость
    Я не вредитель, я — перфекционист — со времен программирования на Ассемблере не люблю избыточность в коде.

    Автор, Вы не перфекционист, а обфускацианист. Сам себе обфускатор:)

    Автор пишет код для себя и только для себя выступая в роли компилятора для 1С с лозунгом «после меня — хоть трава не расти». Для ассемблера подобный подход оправдан и то не всегда.

    Автор, даешь перенос всего кода во внешние DLL. А здесь можно публиковать ассемблерный или бинарный код этих DLL. Мы ведь все Нео и видим блондинок в розовом в строчках кода

     Выполнить(СтрЗаменить(«Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла», «Край», «Конец» + Чего));
    Reply
  12. mymyka

    (9)Отступы съел тэг спойлера,

    Код, устойчивый к ошибкам — это и есть мой код

    Код не имеющий ни одной проверки(лишние строчки же) даже на элементарную заполненость параметров, это НЕ устойчивый код.

    Пример: в код, указанный в статье как эталонный, передаю 2 параметра, ДатаС не заполнена, ДатаПо 09.09.2013, итог — имею массив из 24152 периодов. А если я по этим периодам зарплату считаю? На каждый, например, для 200 сотрудников. Насколько залипнет 1С?. И это

    Данная функция является готовым законченным решением

    ?

    Где легче найти ошибку: в 254 знаках или в 500?

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

    сэкономите деньги заказчика или свою прибыль повысите

    что там выносить в отдельную процедуру? объявления массивов, типов, цикл, запрос, добавление строки? как это позволит «сэкономить» чьи бы то ни было деньги?

    Для примера посмотрите код УТ11 — он достаточно красив, на него можно равняться.

    Так может сказать только тот, кто не дорабатывал УТ11. Отладка миллиона вложенных однострочных функций и тупиковых «Оповестить()» может пошатнуть даже самую стойкую психику. Для примера, при простом перепроведении заказа вызываются функции 24(!!!!) общих модулей.

    Reply
  13. ildarovich

    (10) Тут не о чем сожалеть. Работа должна приносить удовольствие, в том числе и эстетическое. Пожалеть нужно тех, кто занимается этим делом не из любви к искусству программирования, к процессу программирования, а как к скучной обязанности, экономя умственные усилия на работу с кодом. Посмотрите, что пишет Шон МакГраф (Shawn McGrath) — игровой разработчик, создатель популярной психоделической игры для Playstation 3 — паззла-гонки Dyad

    В статье Исключительная красота исходного кода Doom 3

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

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

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

    Reply
  14. mymyka

    (13)Если вам работодатель готов платить за эстетические изыски исключительно из любви к высокому и прекрасному, рад за вас. Сочувствую ему и тому, кто придет после вас. Ибо этот ктулху-диалект 1Сного языка разобрать будет весьма и весьма непросто.

    Но получается, что люди, которым не нравится опера, просто затыкают уши

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

    Reply
  15. ildarovich

    (14) Хорошо, копайте свои ямы, карьеры (недостаточно их ещё?), рубите лес, стригите «бабло». А мне дайте выращивать свой японский садик и делиться своими произведениями с другими. Ну и все-таки, поймите, профессии экскаваторщика и программиста очень разные. Трудно представить экскаваторщика, копающего по ночам на своем экскаваторе «для души». Возможно, когда нибудь потом (мы пришли в этот мир не для того, чтобы торопиться) Вам понадобится заровнять карьер и украсить пейзаж. Одна функция «в японском стиле» для этого у Вас уже есть.

    Reply
  16. help1Ckr

    (105)Gazza,

    согласен во многом с mymyka. Вы таки немного вредитель) ибо молодые юные программисты, которые пришли в 1с ибо не нашли себя на почве ассемблера и пошли в 1с пишут такой код, который потом фиг отладишь. Вам все таки стоит в статье больше внимания уделить пояснению что пункт 9 должен таки использоваться в том случае, когда процедура НИКОГДА не потребует изменения. Сам был увлекся рефакторингом кода пока не понял что все таки должна быть разумная средина) Одно дело сократить процедуру в 14000 строчек кода выбросив ненужные ответвления и сократив его до 3000 строк, другое дело втиснуть оставшиеся 3000 строчек в 10 но настолько непонятных, что доработка будет занимать больше времени чем поддержка 14000

    Reply
  17. eeeio

    На мой взгляд, стоило бы остановиться после шага 5. Итоговый результат тяжел для понимания (и не работает в безопасном режиме).

    Reply
  18. ildarovich

    (17) Мои личные предпочтения — между 2(из-за краткости) и 6(из-за самоконтролируемости кода и гибкости). Я нарочно оставил все варианты, чтобы можно было обсудить и выбрать. Вижу, что прием 9 мало кому понравился, но все же: использовать одну функцию вместо 8-ми показалось очень заманчиво! Планирую еще усилить провокацию и перевести последний вариант на английский — тогда вариантов станет ровно 10 (с 0 по 9) и устроить опрос.

    Reply
  19. МимохожийОднако

    (18)Провокация удалась ))

    Reply
  20. ildarovich

    На форуме открыт ОПРОС ПО ВЫБОРУ ЛУЧШЕГО ВАРИАНТА ФУНКЦИИ — голосуйте!

    Reply
  21. bulpi

    Да вы все не о том спорите, господа. Автор написал статью. Статья интересная ? Несомненно! Нужная ? Конечно! А вот применять описанные приемы, или нет — личное дело каждого. По мне, так и вариант 0 был неплох. Но знать приемы надо, хотя бы для того, чтобы потом разбирать такое вот творчество.

    Reply
  22. Pawlick

    По моему вот этот код будет:

    а) работать быстрее

    б) понятнее для коллег

    Функция РазбитьПериод(ДатаНачало, ДатаКонец)
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ
    | РАЗНОСТЬДАТ(&ДатаНачало, &ДатаКонец, МЕСЯЦ) КАК РазностьДат»;
    Запрос.УстановитьПараметр(«ДатаНачало»,ДатаНачало);
    Запрос.УстановитьПараметр(«ДатаКонец»,ДатаКонец);
    РазностьДат = Запрос.Выполнить().Выгрузить()[0].РазностьДат;
    
    МассивПериодов = Новый Массив;
    
    Интератор = РазностьДат — (РазностьДат * 2);
    
    Пока Интератор <= 0 Цикл
    
    Запрос = Новый Запрос(
    «ВЫБРАТЬ
    | НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ,» + Интератор + «), МЕСЯЦ) КАК НачалоПериода,
    | КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ,» + Интератор + «), МЕСЯЦ) КАК КонецПериода»);
    Запрос.УстановитьПараметр(«ДатаНачало»,ДатаНачало);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Выборка.Следующий();
    
    ЗаписьПериода = Новый Структура;
    ЗаписьПериода.Вставить(«НачалоПериода», Выборка.НачалоПериода);
    ЗаписьПериода.Вставить(«КонецПериода», Выборка.КонецПериода);
    МассивПериодов.Добавить(ЗаписьПериода);
    Интератор = Интератор + 1;
    
    КонецЦикла;
    
    Возврат МассивПериодов
    
    КонецФункции

    Показать

    Reply
  23. mymyka

    (22)тут есть тег кода с подсветкой )

    Reply
  24. mymyka

    (24)Сейчас тебя сожрут за запрос в цикле )

    Reply
  25. Pawlick

    (25) mymyka,

    Возможно…

    Но если добавить проверку на пустые даты, то …

    Reply
  26. Pawlick

    Ща сделаю формирование текста запроса в цикле, тогда может и не сожрут

    Reply
  27. Pawlick

    Вот. Вариант №2.

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

    Потом выгружаем запрос в таблицу, а из нее уже формируем массив.

    Хотя для реальной задачи формировать массив нет необходимости: можно вернуть сразу таблицу.

    Функция РазбитьПериод1(ДатаНачало, ДатаКонец)
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ
    | РАЗНОСТЬДАТ(&ДатаНачало, &ДатаКонец, МЕСЯЦ) КАК РазностьДат»;
    Запрос.УстановитьПараметр(«ДатаНачало»,ДатаНачало);
    Запрос.УстановитьПараметр(«ДатаКонец»,ДатаКонец);
    РазностьДат = Запрос.Выполнить().Выгрузить()[0].РазностьДат;
    
    МассивПериодов = Новый Массив;
    
    Интератор = РазностьДат — (РазностьДат * 2);
    Запрос = Новый Запрос;
    Текст = «»;
    
    Пока Интератор <= 0 Цикл
    
    Текст = Текст +
    «ВЫБРАТЬ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ,» + Интератор + «), МЕСЯЦ) КАК НачалоПериода,
    | КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ,» + Интератор + «), МЕСЯЦ) КАК КонецПериода
    | ОБЪЕДИНИТЬ » + Символы.ПС;
    
    
    Интератор = Интератор + 1;
    КонецЦикла;
    
    Текст = Лев(Текст,СтрДлина(Текст) — 14);
    Запрос.Текст = Текст;
    Запрос.УстановитьПараметр(«ДатаНачало»,ДатаНачало);
    //
    Выборка = Запрос.Выполнить().Выгрузить();
    
    Для Каждого Строка Из Выборка Цикл
    
    ЗаписьПериода = Новый Структура;
    ЗаписьПериода.Вставить(«НачалоПериода», Строка.НачалоПериода);
    ЗаписьПериода.Вставить(«КонецПериода», Строка.КонецПериода);
    МассивПериодов.Добавить(ЗаписьПериода);
    
    КонецЦикла;
    
    Возврат МассивПериодов
    
    КонецФункции

    Показать

    Reply
  28. ildarovich

    (28)

    Худенькая девушка считает себя толстой. Толстая — жирной. А жирная одела леопардовые лосины и красавица!

    К чему это я? — Посмотрите на свой код со стороны! Во-первых, он не работает. Задайте интервал с 1-го по 14-е сентября — вываливается с ошибкой. С 1-го сентября 2000 года — интервалы «не те». А почему так? — Где-то спряталась ошибка! В 31-ой строке и 1089 символах Вашего кода есть где спрятаться. Во вторых, если читать код со скоростью 100 символов в минуту, только на чтение Вашего кода уйдет 10 минут, а моего — 2,5 минуты. А ведь, чтобы понять код, нужно его хотя бы прочитать, а возможно, и не один раз. Так что мой код понимается быстрее. В-третьих, время выполнения Вашего кода в 10!!! раз больше моего (проверял на 200 месяцах — 0,140 сек против 0,016, при этом из-за чувствительности таймера выигрыш может быть и больше). Использовать запросы в этой задаче — мешать чай в стакане ковшом экскаватора — это не то, чтобы не эстетично, а еще и не гигиенично.

    Reply
  29. krv2k

    (0) Автор, попробуйте подумать в другом направлении:

    1) берем вариант 2

    2) добавляем две новые универсальный функции «НачалоПериода(Дата, Период)» и «КонецПериода(Дата, Период)» (аналоги функций из языка запросов)

    3) получаем компактный, понятный и универсальный вариант

    Reply
  30. ildarovich

    (30) Отличное предложение! — Правда, придется себя сдерживать, чтобы не написать

    Функция НачалоПериода(Дата, Период)
    Выполнить(СтрЗаменить(«Возврат НачалоЧего(Дата)», «Чего», Период))
    КонецФункции

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

    Также обратите, пожалуйста, внимание на вариант 5. Он кажется более громоздким, но это пример самоконтролируемой функции, записанной через требования к результату.

    Ну и наконец, если Вас интересуют другие примеры сублимированного кода 1С, обратите внимание на мой блог.

    Reply
  31. krv2k

    (31)

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

    Всё, что идёт после варианта №2, считаю деструктивным рефакторингом, здесь мне ближе позиция (2). Но это ИМХО, ничего личного.

    Также обратите, пожалуйста, внимание на вариант 5. Он кажется более громоздким, но это пример самоконтролируемой функции, записанной через требования к результату.

    Может, я и не прав, но для себя всегда отделяю рефакторинг от оптимизации. Соответственно, выработалось правило: если понимание кода другим разработчиком (большинством других разработчиков) усложняется — это деструктивный рефакторинг, и пользы от него нет, только вред.

    Ну и наконец, если Вас интересуют другие примеры сублимированного кода 1С, обратите внимание на мой блог.

    Спасибо, на досуге почитаю.

    Reply
  32. Pawlick

    (29) Ув. ildarovich!

    Худенькая девушка считает себя толстой. Толстая — жирной. А жирная одела леопардовые лосины и красавица!. К чему это я?

    А Действительно, к чему ?!

    Вы уж меня простите, я немножко Ваши мысли в кучу соберу:

    1. По условиям задачи, установленным ВАМИ:

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

    далее Вы пишите:

    Задайте интервал с 1-го по 14-е сентября

    Что то я в Ваших «стараниях» не увидел «функции разбивающей период времени с 1 по 14 сентября на отрезки, принадлежащие различным месяцам.»

    Может на калькуляторе попробуете?

    2.

    Посмотрите на свой код со стороны! А ведь, чтобы понять код, нужно его хотя бы прочитать, а возможно, и не один раз. Так что мой код понимается быстрее.

    Да, особенно в Варианте 6. Я его пока читал все понял… Даже до конца не прочитал, а уже все понял.

    А потом перешел к варианту 7 и 8 и … бросил: легче самому нибудь придумать. Да еще и отладить нельзя. Замечательный «рефакторинг». А при разнице выполнения в милисекундах при 200 периодах ЧИТАБЕЛЬНОСТЬ ИМХО, будет являться ОСНОВНЫМ ПОКАЗАТЕЛЕМ УДАЧНОГО РЕФАКТОРИНГА. Включите мой вариант в голосование, там видно будет, чей читабельнее…

    Ну и напоследок:

    3. Я Вам Вас процитирую:

    В статье Рефакторинг без тормозов (десять приемов в одной задаче) было предложено ДЕСЯТЬ! разных вариантов решения одной и той же задачи, возникшие в процессе «улучшения» кода функции. В том числе довольно неоднозначные и даже провокационные по своей форме.

    Использовать запросы в этой задаче — мешать чай в стакане ковшом экскаватора — это не то, чтобы не эстетично, а еще и не гигиенично.

    «Довольно неоднозначное и даже провокационное по своей форме решение» использование оператора Выполнить(), помещая в него текст с кодом, я бы назвал «порнографично».

    Ваша статья: это бравада, «смотри как я умею, вот так умею, и так умею». И уж к рефакторингу она ТОЧНО не имеют НИКАКОГО отношения. На практике ни один вменяемый программист не будет использовать Ваш вариант №8.

    Reply
  33. Pawlick
    Во-первых, он не работает. Задайте интервал с 1-го по 14-е сентября — вываливается с ошибкой.

    при заданных датах с 1-го по 14-е сентября возвращает массив с одним элементом:

    01.09.2013 00.00.00 — 31.09.2013.23.59.59,

    все работает.

    Что касается периода с 01.09.2000, действительно, результат был не корректен: спешил, писал, пракически без проверки.

    Выкладываю исправленный вариант.

    Reply
  34. Pawlick

    Опять почему то разукрашка не сработала, выкладываю в чистом виде:

    Функция РазбитьПериод(ДатаНачало, ДатаКонец)
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ
    | РАЗНОСТЬДАТ(&ДатаНачало, &ДатаКонец, МЕСЯЦ) КАК РазностьДат»;
    Запрос.УстановитьПараметр(«ДатаНачало»,ДатаНачало);
    Запрос.УстановитьПараметр(«ДатаКонец»,ДатаКонец);
    
    РазностьДат = Запрос.Выполнить().Выгрузить()[0].РазностьДат;
    
    МассивПериодов = Новый Массив;
    
    Запрос = Новый Запрос;
    
    Интератор = 0;
    Пока Интератор <= РазностьДат Цикл
    
    Запрос.Текст = Запрос.Текст +
    «ВЫБРАТЬ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ,» + Интератор + «), МЕСЯЦ) КАК НачалоПериода,
    | КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ,» + Интератор + «), МЕСЯЦ) КАК КонецПериода
    | ОБЪЕДИНИТЬ » + Символы.ПС;
    
    Интератор = Интератор + 1;
    КонецЦикла;
    
    Запрос.Текст = Лев(Запрос.Текст,СтрДлина(Запрос.Текст) — 14);
    
    Запрос.УстановитьПараметр(«ДатаНачало»,ДатаНачало);
    
    ТаблицаПериодов = Запрос.Выполнить().Выгрузить();
    
    Для Каждого Строка Из ТаблицаПериодов Цикл
    
    ЗаписьПериода = Новый Структура;
    ЗаписьПериода.Вставить(«НачалоПериода», Строка.НачалоПериода);
    ЗаписьПериода.Вставить(«КонецПериода», Строка.КонецПериода);
    МассивПериодов.Добавить(ЗаписьПериода);
    
    КонецЦикла;
    
    Возврат МассивПериодов;
    
    КонецФункции

    Показать

    Reply
  35. wbazil

    прочитал статью с большим удовольствием, спасибо больше

    в результате чтения получилась небольшая таблица

     мПер = РазбитьПериод0(Дата(1175,05,02),Дата(2213,11,15)); //320
    мПер = РазбитьПериод1(Дата(1175,05,02),Дата(2213,11,15)); //225
    мПер = РазбитьПериод2(Дата(1175,05,02),Дата(2213,11,15)); //160
    мПер = РазбитьПериод5(Дата(1175,05,02),Дата(2213,11,15)); //310
    мПер = РазбитьПериод6(Дата(1175,05,02),Дата(2213,11,15)); //300
    мПер = РазбитьПериод7(Дата(1175,05,02),Дата(2213,11,15)); //210
    мПер = РазбитьПериод8(Дата(1175,05,02),Дата(2213,11,15)); //85
    мПер = РазбитьПериод9(Дата(1175,05,02),Дата(2213,11,15)); //85
    

    Показать

    в конце после комментария указано время в миллисекундах

    результат от первого и последнего отличается в 3,8 РАЗА!! это поражает

    хотя для себя я бы остановился на РазбитьПериод2 как выигрыш в два раза уже получен, а код ещё читабелен. результат 8 и 9 конечно отличный, но увидеть первый раз такой код в нем без «бутылки» не разобраться.

    Reply
  36. krv2k

    (37) wbazil, Напишите варианты 8 и 9 одной строкой, результат будет ещё лучше.

    Reply
  37. wbazil

    результат хоть и не на много но лучше:

    73

    79

    82

    78

    78

    Reply
  38. RailMen

    (4) достойно!

    Обратил внимание только сейчас на ваше имя.

    Хотя на этой недели с ребятами ознакомились с «батерфляем». Очень достойно.

    Голосую за Вариант 6.

    Выполнить() — это не безопасно и имеет смысл применять в очень ограниченных случаях.

    Дожимать рефакторинг разбития периода до Выполнить() — это уже не перфекционизм, а полудикий трешь.

    (36) Что касается использования Запроса для решения этой задачи — это не обосновано. А если надо все выполнить на клиенте? Будете сервер вызывать? А вот ildarovich не будет! Он может свою функцию вставить в общий модуль и задать ему свойства «клиент» и «сервер». И спокойно вызывать ее и с клиента и с сервера, когда потребуется.

    Сам разность дат вычислял с применением запроса. Пока не заморочился с клиент серверной архитектурой.

    Reply
  39. RailMen

    (36) Товарищ…(где моя металлическая линейка)…запрос то в цикле…

    Reply
  40. RailMen

    (4)

    Вот тут:

    «Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла»

    дважды встречается в тексте «Край(А)», а это значит…

    Reply
  41. ildarovich

    (42) В черновике статьи юмора было больше. Интересно, что одной из шуток была именно эта.

    Reply
  42. kuzev

    ildarovich, твоя статья мне напоминает решение головоломки, целью решения которой является получение удовольствие от процесса. Разминка для ума, так сказать.

    Ты не одинок, тоже страдаю периодически =) Ниже мой велосипед начала 90-х. Задача для cебя была — минимум строк на BASIC-е. Сейчас смотрю с ужасом =)

    10 INPUT «АРАБСКОЕ ЧИСЛО: «; А$

    20 FOR I=0 TO LEN(A$)-1

    30 X=VAL(MID$(A$,LEN(A$)-I,1))

    40 IF X=4 OR X=9 THEN B$=MID$(«IXCM»,I+1,1)+MID$(«VXLCDM»,I*2+(X+1)/5,1)+B$

    50 IF X<4 THEN B$=MID$(«IIIXXXCCCMMM»,1+I*3,X)+B$

    ELSE IF X>4 AND X<9 THEN B$=MID$(«VLD»,I+1,1)+MID$(«IIIXXXCCCMMM»,1+I*3,X-5)+B$

    60 NEXT I

    70 PRINT «РИМСКОЕ ЧИСЛО: «; B$

    Reply
  43. asved.ru
    perl -e ‘$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`~{;;y; -/:-@[-`{|~};`-{/» *-;;s;;$_;see’
    Reply
  44. kot30688

    Интересный вариант. А если организовать все это дело в запрос, не в цикле, а «прямой» — к любому периодическому регистру накоплений, периодичность запрашивать в нужном отрезке времени (хоть до секунды) — не читабельней и быстрее ли это будет?

    Reply
  45. fzt

    Все было хорошо до варианта 5.

    Было легко читать, легко расширить, легко отладить.

    Дальше пошли крайности. Да так тоже будет работать, но это неприемлемо. Трудно читать, трудно сопровождать и чтобы отладить — придется модифицировать код. Я бы не заострил своё внимание, если не комментарии автора. Он уверен что так нужно делать.

    Увидев у своих кодеров что-то похожее на варианты старше 4, они бы рисковали стать безработными, пока получали по ушам.

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

    Мои уважаемые коллеги. Помните что ваш код вы можете не вспомнить через пару лет. Пишите понятно. «Крутые» программисты конечно нужны, однако «круто» написанный код — не нужен вообще никому. Если где-то вам пришлось до оптимизироваться до таких ужасов, скорее всего у вас проблемы с архитектурой проекта.

    И я практиковал ассемблер. В ваших байтах по сколько бит бывало? 😉 C,Cpp,Delphi,php,python,java,js etc etc.. не просто знаю кучу страшных слов, а реально умею ими работу работать. В данный момент практикую с микроконтроллерами. Знаешь, даже с ними уже нет проблем, когда не влазит байт, или даже килобайт. Памяти много и она дешевая.

    Reply
  46. ildarovich

    (47) fzt, вы пишете

    Он уверен что так нужно делать

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

    В статье я предложил 10 приемов для использования не всегда всех вместе, а каждого при необходимости и с оговоркой рисков. В комментарии (18) я уже написал

    Мои личные предпочтения — между 2(из-за краткости) и 6(из-за самоконтролируемости кода и гибкости). Я нарочно оставил все варианты, чтобы можно было обсудить и выбрать

    А суть варианта 5 вы поняли? — Она весьма интересна. Или не стали вникать из-за его «многобуквенности»? А как вы относитесь к приемам 7, 8 и 10?

    Reply
  47. ildarovich

    (45) asved.ru, это сарказм?

    Reply
  48. asved.ru

    (49) это как напоминание, до чего может довести особо нездоровый рефакторинг, так и указание, что в таком случае делать.

    Reply
  49. kote

    (22)

    Быстрее не будет.

    Будет медленнее.

    «Дергать» БД на каждой итерации очень «расточительно»..

    Код 1С будет работать заметно шустрее.

    Особенно, если функцию вызывать из внешнего цикла на небольших входных данных.

    Reply
  50. kote

    Немного некорректно подощли к метрике сложности..

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

    Reply
  51. puzakov

    Ужасный пример рефакторинга. Избавление от цикломатической сложности своей целью подразумевает снижение сложности кода. А тут всё с точностью до наоборот, сложность кода только повышается.

    Reply
  52. puzakov

    (5)

    В нем НИЧЕГО НЕ ГОВОРИТСЯ об облегчении понимания программы. Рефакторинг — это любое улучшение качества кода, борьба за его чистоту.

    В моем понимании чистота кода — это отсутствие необоснованной избыточности

    Приведу в пример лютый трешак, который бродит по интернету

    Функция ПадежС(z1,Знач z2=2,Знач z3=»*»,z4=0) Экспорт
    z5=Найти(z1,»-«);z6=?(z5=0,»»,»-«+ПадежС(Сред(z1,z5+1,СтрДлина(z1)-z5+1),z2,z3,z4));z1=?(z5=0,z1,Лев(z1,z5-1))//под составные слова
    z1=НРег(?((z2<0)и(z4>1)и(z1<>»»),Лев(z1,1)+».»,z1));
    z7=Прав(z1,3);z8=Прав(z7,2);z9=Прав(z8,1);
    z2=?(((z4=2)и((z3=»а»)или(z3=»ы»))и(Найти(«бвгджзклмнопрстфхцчшщъиеу»,z9)>0))или((z4=2)и(z3=»ч»)и(Найти(«оиеу»,z9)>0))или((z4=1)и(Найти(«мия мяэ лия кия жая лея»,z7)>0)),1,Макс(z2,-z2));
    z5=СтрДлина(z1);
    z10=Найти(«ая ия ел ок яц ий па да ца ша ба та га ка»,z8);
    z11=?(z4=1,?(Найти(«оеиую»,z9)+Найти(«их ых аа еа ёа иа оа уа ыа эа юа яа»,z8)>0,-1,?((z3=»а»)или(z3=»ы»),?(z10=1,8,?(z9=»а»,?(z10>18,3,9),-1)),?(((Найти(«ой ый»,z8)>0)и(z5>4))или(Найти(«гий жий кий ний чий хий ший щий»,z7)>0),10,0))),0);
    z11=?(z11=0,?(z10=4,7,Найти(«.чайяь»,z9)), z11);
    z12=Найти(«лец вей дец пец мец нец рец вец аец иец ыец бер бей»,z7);
    z14=?((z11=10)и(z2<>5),?(Найти(«чшщ»,Лев(z7,1))+Найти(«жий ний»,z7)>0,»е»,»о»),?(z1=»лев»,»ьв»,?((Найти(«аеёийоуэюя»,Сред(z1,z5-3 ,1))+Найти(«аеёийоуэюя»,Лев(z7,1))=0)и(z12<>41),»»,?(z10=7,»л»,?(z10=10,»к»,?(z10=13,»йц»,?(z12=0,»»,?((z12<9)или(z12=49),»ь»+?(z12=1,»ц»,»»),?(z12<33,»ц»,?(z12<45,»йц»,»р»))))))))));
    z14=?((z2=1)или(z11<0)или((z4=3)и(z3=»ы»)или(«»=z1)),z1,Лев(z1,z5-?((z11=8)или(z14<>»»)или(z11=10),2,?(z11>2,1,0)))+z14+СокрП(Сред(«а у а «+Сред(«оыыыоео»,Найти(» внтчц»,z9)+1,1)+»ме           а у а еме «+?(Найти(«гжкхш»,Лев(z8,1))>0,»и»,»ы»)+» е у ойе я ю я ем»+?(z10=16,»и»,»е»)+» и е ю ейе и и ь ьюи и и ю ейи ойойуюойойойойу ойойгомуго»+?((z14=»е»)или(z10=16)или(Найти(«гой хой кой»,z7)>0),»и»,»ы»)+»мм»,10*?((z11=6)и(z3=»ч»),4,z11)+2*z2-3,2)));
    Возврат ?(z4>0,ВРег(Лев(z14,1))+Сред(z14,2),z14)+z6;
    КонецФункции

    Показать

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

    Reply

Leave a Comment

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