Показаны сообщения с ярлыком значение. Показать все сообщения
Показаны сообщения с ярлыком значение. Показать все сообщения

суббота, 4 мая 2019 г.

Облегчаем чемодан

Сезон отпусков начался, а значит грузоперевозки смещаются в сторону пассажиров. Всё больше авиа-компаний предлагают билеты без оплаты багажа или снижают вес ручной клади. Даже железнодорожные и автобусные турникеты проверяют объём чемодана. Как же при таком натиске оплаты за каждый перевес умудриться моднице выглядеть в отпускные дни или на корпоративных, командировочных тусовках разнообразно и соответственно случаю? На каждый день нужны 2-3 наряда, к которым подходит разная обувь. Не уместно в утренних кроссовках для зарядки прийти на ужин в ресторан, или в пляжных шлёпанцах в офис.
Для уменьшения количества нарядов уже давалась подсказка в виде костюма-перевёртыша. Из четырёх деталей двустороннего цвета можно скомпоновать уйму нарядов: длинный сарафан складывать в юбку или мини-платье, два рукава могут быть длинными или короткими, четвёртый элемент - накидка - может стать шляпкой или топиком.
Многофункциональные части наряда
Но как же к разным нарядам уложить в чемодан столько же разных туфель, босоножек, шлёпок, танкеток? Некоторые производители обуви предлагают сменный верх для толстой подошвы, другие меняют каблук. Но, к сожалению, платформа не всегда в моде, а разница высоты каблука не самым лучшим образом влияет на супинатор. Подобрать же удобную колодку - задача всегда очень индивидуальная. Считаю, что для каждой высоты каблука должен быть своя основа. Поэтому предлагаю разделить отпускную обувь на три части: подошва, каблук и верх. Их легко и просто можно уложить в чемодан. Если же они из дерева или композитного пластика, то и общий вес багажа значительно снизится.
Подошва без каблука и верха, вид сбоку
Подошва без каблука и верха, вид на отверстие для крепления каблука методом поворотной защёлки
Виды съёмного каблука - шпилька, устойчивый
Верх шлёпанцев можно сшить из кусочков кожи или ткани
Верх босоножки можно изготовить самостоятельно из ниток или ткани
Верх классических "лодочек" лучше закупать у обувщиков-профессионалов
Другой вариант экономии - одна подошва с каблуком, но сменным верхом и колпаками на каблук. Цветовое сочетание каблука и верха быстро сменить, если верх и колпак крепить на винтики. При этом винтик каблучного колпака будет служить подбивкой, то есть можно его делать из пластмассы для снижения уровня звука при ходьбе.
Разноцветные колпаки на каблук
Ещё одно преимущество от обуви со сменными деталями - материал производства. Ведь это вполне может быть вторсырьё - пластик бутылочный.
Обувщики и текстильщики, давайте сделаем приятное и дамам, и носильщикам их чемоданов - значительно сократим количество вещей и вес багажа.  

понедельник, 15 апреля 2019 г.

Обратная совместимость

Регрессионное тестирование для каждого продукта проводится в своём направлении. В случае обнаружения критичного бага у пользователя должна быть возможность отката до предыдущей версии. Но если в результате такого отката данным будет нанесён урон больший, нежели неудобства новой версии, то считайте такую проблему не просто регрессией, но и фатальной.
Очередной пример вышеописанной регрессии предоставила компания ConquestSS сразу в двух продуктах ClearSQL ver#7.1 и SQLDetective ver#5. Когда в 2015 году для ClearDB персональные данные (пароль к БД) стали шифроваться, то моё замечание о невозможности восстановления паролей через возврат к предыдущей версии восприняли как негативный и нежелательный тест. Разработчик в новой версии добавил кодирование пароля, но не делал конвертацию старых данных. Тогда не было владельцев продукта, готовых обновиться до новой версии. На стороне пользователя потеря паролей не проявилась. Да, соглашусь с мнением, что пароль - это не те данные, которые стоит хранить даже в зашифрованном виде, но у разработчиков ConquestSS и к любым другим настройкам аналогичное отношение. Старые, привычные установки не конвертируются в новую версию, а затираются значениями по-умолчанию без предупреждения. О чём не раз жаловались юзеры. Алгоритм перевода на новые настройки давно известен (сохранить старые, добавить новые параметры, предупредить о новых возможностях и вариантах восстановления прежних), но в среде программистов ConquestSS им напрочь пренебрегают.
Поскольку ни в Online Help, ни в Release Notes ничего не сказано о том, что после апгрейда пропадут данные, то считаю своим долгом тестировщика предупредить текущих пользователей ClearSQL ver#7.0 и SQLDetective ver#4 о необходимости сохранить прямо сейчас ветки реестра "HKEY_CURRENT_USER\Software\ClearSQL\DB Connect" и "HKEY_CURRENT_USER\Software\SQLDetective\Splash\ConnectionHistory" соответственно продуктам или Preferences в файл. Это позволит вам вручную восстановить в предыдущей версии утерянные при апгрейде пароли. Напоминаю, что в ClearSQL ver#7.1 (and higher) и SQLDetective ver#5 пароли к БД, сохранённые в предыдущих версиях, обнуляются при первом же запуске без какой бы то ни было возможности восстановления.
О простоте кодирования паролей в ClearSQL ver#7.0 и SQLDetective ver#4 уже говорилось в статье "Telegram in application with DB connection". Команде разработки потребовалось полтора года после моего напоминания для перенесения алгоритма более серьёзного кодирования паролей из ClearDB ver#4 в ClearSQL ver#7.1 и в SQLDetective ver#5. Так что, перед обновлением до сегодняшних версий не поленитесь и сделайте себе памятку, ведь столь удобная галка "сохранить пароль" может сыграть с вами очень злую шутку - не восстановит значения в новой версии, и даже механическая память рук ничем не поможет.
А всем тестировщикам ПО рекомендую не только проводить тест на обратную совместимость, но и вести профилактическую работу по предотвращению багов. Вроде бы удобство - опция для сохранения и авто-восстановления данных, но не для всех значений она может поддерживать законы безопасности приложения. Ещё одним примером такой юзерской прихоти является отдельная возможность выгрузки в XML файл всех сохранённых на машине коннектов к базе. В своё время мне пришлось потратить немало усилий, чтобы из прикреплений к OSD сообщению удаляли эти записи, потому что они несут персональную информацию, зачастую бесполезную для техподдержки ConquestSS. Но полагаю, что тот же юзер, который предложил сохранять пароли, сам и предложил экспортировать коннекты. А ведь это первый путь к хакерству. Если пользователь меняет комп, то в Online Help есть подробная инструкция по переносу настроек. Насколько часто нужна фича экспорта-импорта всего списка коннектов и кому? Ответ очевиден - только тому, кому временно стал доступен чужой ПК. Да, через сохранение всех настроек (Preferences) в файл тоже быстро можно скопировать все коннекты, но при этом ещё много локальных параметров (ключ лицензии, опции анализатора) придётся корректировать после импорта. Так что, считаю фичу экспорта-импорта коннектов вредной, а не полезной. И рекомендую подобные им новшества пресекать на первоначальном этапе разработки. Тогда не придётся выдумывать "защиту от дурака" в виде излишних шифрований или подтверждений опасных шагов. А владельцы продуктов и особенно администраторы баз должны перестать использовать опцию сохранения паролей, дабы хоть малость усложнить нежелательным элементам доступ к данным. Хотя, подобрать пароль, зная имена схем и баз, можно довольно просто. О чём немало говорили и Pete Finnegan, и Александр Поляков.

понедельник, 28 января 2019 г.

Зал-гармошка

Любительские театры ограничены пространством. Зачастую, им достаются небольшие кабинеты в Доме Культуры или школе. Удача, если на части пространства выстроен подиум, ограничивающий сцену и зрительный зал. Тогда зрителям задних рядов хоть что-то видно.
Если стулья для зрителей складные, то для репетиций и тренингов можно расчищать зал.
Самым эргономичным и удобным решением может стать зал-гармошка, задние ряды которого располагаются высоко (зрителям не придётся вытягивать шею из-за спин впереди сидящих), а на время репетиций весь пол кабинета свободен для тренировки сценодвижений.
Три ряда в разложенном состоянии:
 
Верхняя полка - сидячие места. Верхняя точка спинки на высоте 2,5м от уровня пола, сидушки на высоте 2м от пола. Спинка и сидушка оббиты поролоном (бирюзовые линии), соединяются по методу треугольника гибкими верёвочными креплениями сверху (зелёная линия) и съёмными жёсткими (металлическими) креплениями, как в кроватях-раскладушках, снизу сидушек к стойке подножки (вторая слева вертикальная линия сиреневого цвета) . Стойка со спинкой верхнего ряда (крайняя левая линия синего цвета) крепится к задней стене зала анкерными болтами. Между стойками можно для устойчивости добавить жёсткое металлическое крепление (крючок и петля), параллельное полу на высоте до 0,5м от пола (на всех схемах отсутствует).
Вторая полка - проход верхнего ряда (коричневая линия) и через перегородку (средняя синяя линия) - сиденья среднего ряда расположены на высоте 1,5м от пола. Верхняя точка спинки среднего ряда - 2м. Полка прохода среднего ряда соединяется со стойкой спинки нижнего ряда, сидушка среднего ряда соединяется со стойкой прохода верхнего и среднего ряда съёмным металлическим креплением (крючок и петля) - линии серого цвета. Между каждыми соседними стойками можно для устойчивости добавить жёсткое металлическое крепление (крючок и петля), параллельное полу на высоте до 0,5м от пола.
Аналогично устроен нижний ряд: верхняя точка спинки - 1,5м, сидушка - 1м, подножка - 0,5м от пола. Первый, нулевой ряд (или больше) можно приставить из стульев (лучше со спинкой) к стойке подножки (правая синяя линия) нижнего ряда зала-гармошки. Глубина зала-гармошки в разложенном состоянии - 3м от задней стены. Размеры можно уменьшить, но для данного макета выбран стандарт: высота сидушки и спинки, глубина сидушки, ширина прохода - по 0,5м.
Сократив высоту рядов с 0,5м до 0,25м за счёт опускания проходов, имеем следующую конструкцию:
 
Верхняя точка спинки заднего ряда - 1,75м. Сидушка заднего ряда - 1,25м. Проход заднего ряда - 0,75м. Верхняя точка спинки среднего ряда - 1,5м. Сидушка среднего ряда - 1м. Проход среднего ряда - 0,5м. Верхняя точка спинки нижнего ряда - 1,25м. Сидушка нижнего ряда - 0,75м. Проход нижнего ряда - 0,25м.
В сложенном состоянии все ряды сдвигаются в плоскость к задней стене:
 
Жёсткие крепления-крючки (серые линии) снимаются. Верёвочные (зелёные) соединения сгибаются. Поскольку полки имеют соединения со стойками через дверные навесы, то полки и стойки собираются по направлению к задней стойке. Для удержания сложенного состояния стойки крепятся друг к другу маленькими крючками. Глубина сложенной конструкции будет зависеть от толщины стоек, например, для трёх рядов из 7 стоек - около 0,5м. Максимальная высота сложенного зала-гармошки - до 3,5м. Но если высоту последующих рядов снизить, то высота сложенной конструкции будет 3,25м.
 
Есть ещё один вариант уменьшить высоту сложенной конструкции. Сидушки, как и прежде, складывать вверх к спинке, а подножки раскладывать вниз по задней стойке. Тогда высота сложенной конструкции будет равняться задней стойке 2,5м или 1,75м.
 
В случае складывания горизонтальных щитов всех рядов только вверх, раскладывать придётся всю конструкцию (все три ряда в моём примере). В случае попеременного складывания горизонтальных рядов (сидушки - вверх, подножки - вниз) конструкцию можно растягивать по-рядно, то есть только один ряд или только два ряда, потому что нижняя точка стоек спинки в идеале будет на полу.
Для стоек, сидушек и проходов (синие, сиреневые, бирюзовые и коричневые прямые на схемах) можно использовать деревянные щиты (доски сбитые или клееные, фанера, OSB). Жёсткие крепления (серые линии на схемах) должны быть металлическими, чтобы не увеличивать объём и вес конструкции. Для гибких креплений (зелёные линии на схемах) подойдут верёвки, жгуты или тканевые треугольники, чтобы избежать лишних мобильных креплений (крючки, липучки). Подушки для сидушек и спинок (бирюзовые линии на схемах) следует изготовить из ткани, поролона и приклеить, прибить к щитам или предусмотреть их съёмными на липах (это позволит более плотно собирать конструкцию, но для подушек нужно будет дополнительное место хранения, но эти же маты можно использовать на тренингах). Для постоянных соединений (на схемах места креплений - это углы 0, 90, 180 градусов между прямыми, кроме серых) между вертикальными (стойки, спинки) и горизонтальными (сидушки, подножки) щитами следует использовать дверные навесы, позволяющие складывать конструкцию и удерживать углы.
Для лестницы следует использовать аналогичную технологию. На каждый уровень (подножка, сидушка) делаются ступеньки высотой 0,25м и глубиной 0,25м. Стойку каждой нижней ступеньки не стоит крепить на навес к нижнему щиту, потому что каждые две (в случае единой высоты подножки верхнего/среднего ряда с сидушкой среднего/нижнего ряда), три (в случае межрядовой высоты 0,25м) ступеньки складываются и крепятся к очередной стойке (синие и сиреневые линии на схемах).
Оптимальное количество мест в секции - 3 штуки (ширина ~1,5-2м в зависимости от степени устойчивости и жёсткости щитов-сидушек). Лесенки можно вставлять между каждыми секциями, либо сэкономить место и сделать одну лесенку на 3-5 секций.
Количество рядов может быть любым: от одного до бесконечности. :) Зависит от расстояния между сценой и задней стеной кабинета, отведённого театру, и доступной высоты до потолка.
На внутренней стороне щитов можно расположить крючки или кармашки, которые станут полезны только в собранной конструкции. На них можно развесить костюмы, реквизит в упаковке в дни между спектаклями.
Многофункциональность конструкции заключается в экономии рабочего пространства, удобстве разноуровневых рядов, использовании изнанки в качестве места для хранения вещей.
Фоторяд картонного макета:
Вид сверху на сидушки и проходы.

Вид снизу на соединения по принципу дверных навесов и разъёмных крючков.

Вид сбоку на процесс складывания, раскладывания.

Вид сбоку на собранную конструкцию - не забудьте про удерживающие элементы.

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

Вид сзади на собранную конструкцию - не забудьте про удерживающие элементы.


Тестировщики ПО, зал-гармошка - это напоминание вам:
- об эффективном использовании пространства в интерфейсе продукта;
- о своевременной и полноценной очистке рабочего пространства после использования;
- о своевременности подготовки переменных перед непосредственным использованием;
- о конструктивном и многофункциональном подходе при написании и обращении к подпрограммам в коде;
- о выявлении и проверке граничных значений;
- о знании и применении стандартов удобств.

понедельник, 5 ноября 2018 г.

Cheat-sheet for Unicode

Текстовые редакторы и Юникод
Cheat-sheet для текстовых редакторов включает в себя не мало пунктов, но порою до юникода дело редко доходит. А когда продукт выходит на международный рынок и особенно на азиатский, то наваливаются проблемы для глобальных переделок.
Кроме командной строки (cmd, sql*plus и т.п.), которая тоже имеет свои настройки перекодировки отображаемых символов (свойства приложения "cmd.exe", команда "chcp 1251" или "alter session set nls_lang.."), в интерфейсном приложении существует не мало элементов для работы с текстом:
- не редактируемая подпись интерфейсного элемента (label, caption);

- однострочный, одноячеечный редактор (edit);

-- в том числе и масочный, с предварительно зарезервированными символами или отображающий символы в перекодированном виде (mask-edit = calendar, password);

- многострочный, одноячеечный редактор (memo, text-editor);

-- в том числе и нередактируемые списки одной колонки (list, combobox);
-- либо комбинация одноячеечного редактора с отображаемым списком (edit+list, edit+combobox), тестировать которые необходимо в комплексе с родительским элементом;

- многострочный, многоячеечный грид, таблица (grid, table of cells from rows and columns);
-- в том числе и открываемые для каждой ячейки соответсвующие редакторы (cell-edit, cell-memo, cell-mask-edit, cell-list, cell-combobox, cell-grid), тестировать которые необходимо в комплексе с родительским элементом;

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

либо база изначально создаётся в конкретной кодировке.

Для проверки всевозможных символов достаточно клавиатуры 101-клавишной, вводя не только видимые на клавишах символы, но и через комбинацию функциональной или Alt клавиши и цифрового кода. Некоторые редакторы имеют встроенный выбор символов из зарезервированных списков. Ленивые тестировщики могут взять символы с сайтов стран южно-азиатского региона, не забыв выставить соответствующую настройку файлу при сохранении. Спасибо щедрым соратникам, которые давно уже выложили в сеть разнообразные примеры.
Тест граничных значений актуален для любого элемента, в особенности отправляющего данные в базу.
Для негативных тестов, кроме размера, следует брать различный формат данных - большие тексты, вариации кодировок (байт на символ), видео, картинки и исполняемый код в различной системе исчисления.
Объём и необходимость проверки безопасности будет вытекать из предназначения элемента: визуализация символов, разрешённость правки, замена стандартного текста исполняемым кодом.

среда, 17 октября 2018 г.

Cheat sheet for options

Чит-лист для опций в виде check-boxes и radio-buttons
- наименования
-- короткие
-- однозначные
-- логически ясные без дополнительных подсказок
--- наличие хинта для сложного наименования
--- примеры использования в статье хелпа
- значения по-умолчанию
-- описаны в хелпе
-- в check-boxes все могут быть нулевыми
-- в группе radio-buttons одно значение выбрано
-- для radio-buttons обязательна группа элементов
- граничные значения
-- check-boxes двузначные (включено/выключено)
-- check-boxes трёхзначные (все включенные/выключенные дочерние включают/выключают родительский check-box, неполный выбор дочерних ведёт к полувыбору [серая галка] родительского check-box)
-- все check-boxes могут быть включены/выключены одновременно
-- только один radio-button может быть выбран
-- все значения radio-buttons не могут быть нулевыми одновременно
-- количество check-boxes ведёт отсчёт от 1
-- количество radio-buttons не может быть меньше 2
- функционал
-- логика check-boxes в коньюнкции "И-&"
-- логика radio-buttons в дизъюнкции "ИЛИ-V"
-- значение опции должно сохраняться и восстанавливаться при переоткрытии окна с опциями и перезапуске приложения на одной и той же машине или при том же логине
-- применение в приложении каждой отдельной опции
-- применение в приложении комбинацией группы опций

пятница, 22 июня 2018 г.

ГКЧП - Где, Как, Что Править?

Команда разрабатывает несколько десктопных продуктов с некоторыми едиными модулями, какие-то продукты являются как самостоятельными, так и частью других, собственный сайт для поддержки продуктов как самостоятельный продукт тоже имеет тесные связки с десктопными.
Самописная система ведения задач была удобна, но недостаточна для распределённой команды. Поэтому был выполнен переход на Jira. Каждому продукту было присвоено своё имя в BTS (Bug Tracking System), а несколько глобальных модулей (код исправляется в одном скрипте, а при компиляции каждого продукта исправления автоматически попадают в билды) были перенесены из старой BTS в новую в продукт Global Modules, также задачи по сайту были импортированы в отдельный продукт Jira.
В старой BTS возможно было использовать единый список версий продуктов, а для закрытия багов приписали небольшой интерфейс. В Jira, к сожалению, нет возможности использовать сквозной список версий продуктов, поэтому в продукте Global Modules приходится создавать дубликаты номеров билдов по каждому скомпилированному продукту (но этот утомительный ручной труд был автоматизирован спустя 3 года мучений).
Пока команда состояла из 7 программистов и одного тестировщика, то проблем с описанием и пониманием задач не случалось. Когда же команда разработчиков сменилась на 70% и вдвое увеличилась, то появилась необходимость расшифровывать устоявшиеся понятия и правила. А чтобы не тратить на каждую задачу драгоценное время старожил, создавались документы с описанием корпоративных правил. Для более быстрого и эффективного запоминания всех сложностей, придуманных PM, мной была предложена мнемоника.

ГКЧП
или Как Правильно Читать баГ/импрув?
Где, Как, Что Править?
ГДЕ
* Определяем продукты, в которых надо фиксить. Это видно из номера:
     Prod_1-[issuenumber] - только в Product_1;
     Prod_2-[issuenumber] - в Product_2 и может быть в Product_3;
     Prod_3-[issuenumber] - в Product_3 и скорее всего в Product_2;
     GM-[issuenumber] - в Product_1, Product_2, Product_3 и может быть на сайте;
     WEB-[issuenumber] - на сайте и может в Product_1, Product_2, Product_3
* Определяем модуль или функционал, как часть продукта. Это видно из поля Component.
* Определяем список версий, в которых нужно внести исправления. Для этого на сайте смотрим номер текущей версии (Support -> Release History -> [ProductName]) и сравниваем его с номером билда, в котором выявлен баг/импрув. Это видно по значению поля Affect Versions. Если баг/импрув из числа GM, то номер Affects Versions префиксован кратким наименованием продукта. Если номер версии совпадает с точностью до релиза, то правку вносим только в текущие поддерживаемую и разрабатываемую. Если версия отлична по Мажору/Минору, то сверяемся в поле Label по наличию значений FIX_IN_PREV_VER и/или FIX_IN_OFFICIAL_VER.
* О том, нужен ли фикс в предыдущей версии или в будущей-разрабатываемой версии говорит поле Label со значениями FIX_IN_PREV_VER и/или FIX_IN_OFFICIAL_VER.

ЧТО
* Определяем объём работ по совокупности значений полей Summary, Description, Attachments. Обычно структура Description нижеследующая:
     [Шаг / Модуль]
     [Пункт / Страница]
     [Что не так?]
     [При каких условиях?]
     Как должно быть?]
         example:
         [Шаги примера]

* Пояснительный скриншот или лог бага, или длинный пример хранится в поле Attachments (атач).
* У кого уточнить детали бага/импрува видно из полей BUG_HUNTER или Reporter.

ПРАВИТЬ/ПРОВЕРЯТЬ
* Если фикс был возвращен на доработку, то в поле Comments имеется причина.
* Проверять фикс надо как с default настройками, так и с описанными в Description или Environment.


среда, 20 июня 2018 г.

Качество кода одним числом

Maintainability Index – величина качества кода

Качество продукта, согласно ISO-9126, состоит из 6 частей (см. Рис.1 "ISO-9126").
Рис.1 "ISO-9126"
Из этих же шести пунктов (см. Рис.1 "ISO-9126") строится и качество кода, которое можно измерить для любого языка программирования. К сожалению, идеального кода не существует и добиться невозможно, как и КПД-100%.
Одна из простейших метрик – количество параметров, которое рекомендуют не более 7: 5 входящих, 2 на выход. Особое место занимают глобальные переменные, наличие которых усложняет код.
Более сложно качество кода вычисляется по формулам, только одна из которых "цикломатическая сложность" пока принята институтом стандартов. Когда научному миру удастся доказать полезность и значимость остальных формул, тестировщики смогут официально ориентироваться на эти лимиты.
Формула расчёта Maintainability Index была выведена достаточно давно Доном Колеманом, Паулем Оманом и Джеком Хегмейстером. Она имеет несколько вариаций для различных языков программирования. Фактически, польза индекса "ремонтопригодности" не только в оценке готового кода, но по этой величине вполне можно спрогнозировать устойчивость кода с учётом будущих исправлений.
Согласно формулам (см. Рис.2 "Две формулы подсчёта количества багов в юните", где TNOpr – общее количество операторов, TNOpd – общее количество операндов, DNOpr – количество уникальных операторов, DNOpd  – количество уникальных операндов) Мариуса Халстеда, если код состоит хотя бы из одного оператора и операнда, то величина багов в этом коде уже не нулевая.
Рис.2 "Две формулы подсчёта количества багов в юните"
Если оценить обе формулы (см. Рис.2 "Две формулы подсчёта количества багов в юните") через их графики, то очевидно, что количество багов в новом и исправленном коде будет нулевым только в "пустой" подпрограмме.
 
Рис.3 "График и формула подсчёта новых багов"
На рисунке 3 "График и формула подсчёта новых багов" верхняя формула для расчёта прогнозируемых багов минимизирована по количеству операторов (1 шт) и операндов (2 шт). Количество багов смотрим по оси Y, количество операторов и операндов (только целые числа) смотрим по оси X. Поскольку рабочей подпрограммы без операторов и операндов не существует, то по графику убеждаемся, что количество багов резко уходит в бесконечность только при нулевых значениях операторов и операндов [0..1], количество багов растёт плавно (y>0 при x>1). 
 
 Рис.4 "График и формула подсчёта недавних багов"
Минимизировав вторую формулу (см. Рис.2 "Две формулы подсчёта количества багов в юните") для расчёта недавних багов и приняв один оператор на пару операторов, получаем по-сути аналогичный график (см. Рис.4 "График и формула подсчёта недавних багов"), когда количество багов равномерно растёт по оси Y и не может быть отрицательным, так как в рабочем коде должен быть хотя бы один оператор и операнд, то есть значения по оси X рассматриваются только целочисленные, начиная с 1.
Итак, мы убедились, что в любом коде всегда есть баги. А об их серьёзности можно судить по величине Maintainability Index (MI).

Из чего же складывается величина качества кода?
Максимальная формула учитывает значения Сложности Халстеда, Цикломатической Сложности, значимые Строки кода и объём Комментариев:
MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln (LOC) + 50 * sin(sqrt(2.4 * COM)), где HV – сложность Халстеда, CC – цикломатическая сложность, LOC – количество строк кода, COM – объём комментариев в коде.
Укороченная формула не учитывает объём комментариев:
MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln (LOC)
Компилируемые языки программирования "не отвлекаются" на комментарии, поэтому для них (например, Си) вполне очевидно использование укороченной формулы. А языки-интерпретаторы (например, SQL) корректнее оценивать по полной формуле, так как комментарии внутри цикла в некоторых языках могут замедлять исполнение программы, поскольку на вычленение незначимых строк тоже нужно время.
Пределы индекса принято рассматривать по следующей таблице (см. Рис.5 "Лимиты Maintainability Index"):
- подпрограмма требует немедленного исправления, если MI упал меньше 65;
- подпрограмму желательно исправить, если MI больше или равен 65, но меньше 85;
- подпрограмма не нуждается в исправлении, если MI равен или больше 85.
Исходя из формулы абсолютное максимальное значение Maintainability Index равно 221 (171-0-0-0+50), но оно не достижимо ни при каком содержимом сорсника.
Рис.5 "Лимиты Maintainability Index"
Об истории лимитов MI можно почитать в статье.

Итак, чем больше индекс, тем лучше код. Рассмотрим способы повышения индекса важности кода.
Более скорый способ увеличения индекса исходя из формулы первой модели "MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln (LOC) + 50 * sin(sqrt(2.4 * COM))" возможен за счёт увеличения объёма комментариев, так как индекс в формуле – наибольшее положительное число "50". Объём комментариев зависит от функции синуса, которая колеблется в пределах [-1..1]. Но поскольку объём комментариев можно исчислять двумя способами – как процент или долю, а значение синуса может быть и отрицательным, то необходимо выяснить оптимальные пределы комментариев. Для этого рассмотрим график функции "y(x)= 50 * sin(sqrt(2.4 * x))" на отрезках [0..100] (при исчислении комментариев в процентах) и [0..1] (при исчислении комментариев в долях от общего кода).
Рис.6 "График комментариев в процентах"
На графике (см. Рис.6 "График комментариев в процентах"), построенном по формуле "y(x)= 50 * sin(sqrt(2.4 * x))", по оси X имеем процентное соотношение комментариев к строкам кода, а по оси Y – величину для расчёта Maintainability Index. 1-2% или 25-26% или 83-84% комментариев дадут желаемый максимум (y=50), 0% или 4% или 17% или 37% или 66% комментариев абсолютно не влияют на Maintainability Index (y=0), 9% или 50-51% комментариев самым сильным образом (y=-50) отрицательно влияют на индекс ремонтопригодности. При этом MI может стать и отрицательной величиной. 
Рис.7 "График комментариев в долях"
На графике (см. Рис.7 "График комментариев в долях"), построенном по формуле "y(x)= 50 * sin(sqrt(2.4 * x))", по оси X имеем долевое соотношение комментариев к строкам кода, а по оси Y – величину для расчёта Maintainability Index. График показывает, что 3-4 комментированные строки кода из 10 рассматриваемых (или каждая третья) максимально помогают увеличить MI, то есть являются самым полезным соотношением.
Итак, если MI упал ниже 65, то по-быстрому его поднять можно вставкой комментариев в каждую третью строку.
Примечания:
- полезность/качество комментариев не рассчитывается формулой, поэтому не стоит забывать, что просто закомментированный код – это не полезные примечания;
- при добавлении комментариев соответственно увеличится и общее количество строк кода.

Шаг второй по повышению индекса устойчивости подпрограммы – снизить количество строк кода, потому что в формуле "MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln (LOC)" наибольший отрицательный индекс "16.2" у величины строк. На графике (см. Рис.8 "График и формула строк кода") видно, например, что 4500 строк уменьшат индекс на 136 пунктов из 171 возможного по формуле. Количество строк в подпрограмме определяется по спецсимволам текста, поэтому парсер обмануть не получится обычным размещением команд в одну строку файла. Единственный вариант – оптимизация кода за счёт объединения и выноса идентичных блоков кода в самостоятельные функции, которые будут рассматриваться как отдельные подпрограммы.
Примечания:
- не забывайте, что при этом увеличится количество параметров и скорее всего даже глобальных;
- блок-схемы, flowchart или UML диаграммы помогают вычленить повторяющиеся блоки хода подпрограммы.
 
 Рис.8 "График и формула строк кода"
Если пойти от обратного и принять в формуле MI(<=65) максимальные значения HV(=1000), CC(=10) и комментариев (sin[X]=1), то в одном юните желательно иметь не более 1500 строк (см. Рис.9 "График максимального количества строк кода и формула с учётом комментариев").
 Рис.9 "График максимального количества строк кода и формула с учётом комментариев"
То есть по формуле Maintainability Index с учётом комментариев мы вывели лимит для оптимального количества строк в подпрограмме: LOC<1500 mi="">=65.
Для формулы второй модели (без учёта комментариев) смотрите рисунок 10 "График максимального количества строк кода и формула без учёта комментариев".
 Рис.10 "График максимального количества строк кода и формула без учёта комментариев"
График по оси Y показывает MI, а LOC по оси X. Из чего следует, что в юните без комментариев для стабильно-устойчивого кода нужно иметь менее 50 строк (см. Рис.11 "Увеличенный график максимального количества строк кода для формулы без учёта комментариев").
 
 Рис.11 "Увеличенный график максимального количества строк кода для формулы без учёта комментариев"
Об иных подробностях строк кода читайте в статье "Source lines of code".

Третий шаг по повышению MI – это снижение сложности Халстеда из части "5.2 * ln(HV)". Максимальная величина Халстеда – 1000. Исходя из этого на графике (см. Рис.12 "График и формула Halstead Volume в рамках MI") видно, что сложность Халстеда максимально может уменьшить индекс ремонтопригодности на 36 пунктов.
 
 Рис.12 "График и формула Halstead Volume в рамках MI"
Все величины Халстеда рассчитываются по операторам и операндам. Напомню, что в выражении "a+b" оператором является плюс, а операндами – переменные "a" и "b". Длина программы по Халстеду – это сумма всех операторов и всех операндов. Словарь юнита он определил как сумму уникальных операторов и операндов. А помножив длину программы на логарифм словаря, Халстед получил объём подпрограммы (или ещё эту величину называют сложностью Халстеда):
HV = ( TNOpr + TNOpd ) * log2 ( DNOpr + DNOpd ),
где TNOpr – общее количество операторов, TNOpd – общее количество операндов, DNOpr – количество уникальных операторов, DNOpd  – количество уникальных операндов. Более подробно о величинах Халстеда читайте в статье "Halstead complexity measures".
Если принять, что на один оператор приходится два операнда, то график функции HV будет приблизительно, как на рисунке 13 "График и функция сложности Халстеда".
 Рис.13 "График и функция сложности Халстеда"
По оси Y смотрим значение HV, а по оси X выбираем количество операторов. Максимальному значению HV=1000 соответствует 45 операторов, и соответственно около 90 операндов (~ два операнда на один оператор).
Для увеличения MI до 65 и выше надо уменьшать HV, то есть количество операторов и операндов. В коде (см. пример на рисунке 14 "Пример сложных и простых вычислений") можно множество простых операций объединить в одну сложную. Это как в начальной школе по арифметике при имеющемся решении задачи в три-четыре действия выполнить расчёт одним действием.
 Рис.14 "Пример сложных и простых вычислений"
На скриншоте из ClearSQL (см. Рис.15 "Пример упрощения кода по HV, MI") показана разница в значениях HV для сложной "hv_1" и простой "hv_2" подпрограмм.
 Рис.15 "Пример упрощения кода по HV, MI"
Уменьшая количество операторов и операндов в коде снижается сложность Халстеда (HV), и как следствие увеличивается (улучшается) индекс ремонтопригодности (MI).

Четвёртый шаг по улучшению MI – снижение цикломатической сложности.
Томас Дж.Маккейб вывел формулу цикломатической сложности юнита как разность рёбер (edges) и узлов (junctions) с добавлением удвоенного количества компонент связности (coherences):
CC = Edges – Junctions + 2*Coherences
Максимальное значение величины Маккейба утверждено Американским Национальным Институтом Стандартов и Технологий (NIST), равно 10, но последнее время расширяют до 15. Нам тестировщикам это значение говорит о необходимом количестве юнит-тестов. Более подробно о цикломатической сложности читайте в статье "Cyclomatic complexity". Цикломатическая сложность снижает индекс ремонтопригодности максимально на 2-3 пункта, поэтому её рассматриваем в последнюю очередь. График (см. Рис.16 "График и формула цикломатической сложности в рамках MI") показывает часть "0.23 * CC" из формулы MI.
 
 Рис.16 "График и формула цикломатической сложности в рамках MI"
По оси X берём целочисленное значение Cyclomatic Complexity (max=10 or 15), по оси Y видим объём снижения (коэффициент – отрицательная величина "-0.23") MI.
Для улучшения MI нужно уменьшать CC, то есть "выпрямлять" ход программы. Но учтите, что иногда сложные условия (композиция нескольких AND и OR) рассчитывается как одно, то есть уменьшается количество узлов и рёбер, следовательно и само значение CC будет меньше.
Рис.17 "Пример кода цикломатической сложности"
В примере (см. Рис.17 "Пример кода цикломатической сложности") процедура threeinone имеет одно сложное условие (CC=4 или CC=2), а процедура oneinthree – три простых условия (СС=4 всегда).

Итак, для оценки качества кода достаточно вычислить только одну величину – Maintainability Index. В слабом юните исправления следует применять по очереди к комментариям кода, количеству строк, операторов и операндов, узлов и связей хода программы. Элементарных знаний математического анализа и школьного курса информатики достаточно специалисту, решившему тестировать код на любом языке программирования, при этом не углубляясь в синтаксис языка.

Полезные ссылки:
* Качественный анализ программного модуля на основе метрик кода
* Don M. Coleman, Dan Ash, Bruce Lowther, Paul W. Oman. Using Metrics to Evaluate Software System Maintainability. IEEE Computer 27(8), 1994, pp. 44-49.
* Paul Omand and Jack Hagemeister. “Metrics for assessing a software system’s maintainability”. Proceedings International Conference on Software Mainatenance (ICSM), 1992, pp 337-344.
* Paul W. Oman, Jack R. Hagemeister: Construction and testing of polynomials predicting software maintainability. Journal of Systems and Software 24(3), 1994, pp. 251-266.
* The Maintainability Index was introduced at the International Conference on Software Maintenance in 1992
* To date, MI is included in Visual Studio (since 2007), in the recent (2012) JSComplexity and Radon metrics reporters for Javascript and Python, and in older metric tool suites such as verifysoft.
* Think Twice Before Using the Maintainability Index
* P. Oman
* J. Hagemeister