Опасность использования значений по умолчанию в обьявлениях

Недавно работал на одним большим проектом написанным на C++, и во время отладки встретился с довольно опасной вещью. Посмотрим на примерах. В начале был некий метод с парой параметров один из которых задаётся по умолчанию в обьявлении:

Class1::SetEditBox(CString const& value, bool isUppercase = true);

И гдето в коде этот метод по разному вызывался:

obj1.SetEditBox(_T("Volume"), false);
 ...
 obj2.SetEditBox(_T("SerialNo"));

Прошло время и обьявление метода немного дополнили:

Class1::SetEditBox(CString const& value, bool isEditable = false, bool isUppercase = true);

В новых местах использование, всё было хорошо, да вот старый код толком никто так и не посмотрел, таким образом после вызова

obj1.SetEditBox(_T("Volume"), false);

isUppercase становился true. Однако, так как обьём обычно задаётся в числах, то без толкого тестирования различных вариантов, такой случай прошёл незамеченным.
Время шло, система росла и становилась сложнее. С каждой сменой команды разработчиков её брались переписывать и оптимизировать и в какой то момент бросали. Метод задействовался в других классах:

Class2::SetListEdit(CString const& value, bool isEditable = false, bool isUppercase = true)
{
    // ...
    obj4.SetEditBox(value, isEditable, isUppercase);
    // ...
}

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

Class1::SetEditBox(CString const& value, bool isNumeric = true, bool isEditable = false, bool isUppercase = true);

На этот раз уже гораздо больше кода следовало просмотреть и изменить, но как то изменение забылось и прошло незамеченным. И далее код ещё более расширился:

Class3::AddListEdit(CString const& value, bool isUppercase = true)
{
    Class2 obj5;
    obj5.SetListEdit(value, isUppercase);
}

В результате мы имеем ошибку, которую я назвал «Shifting Boolean».
Таким образом вызов Class3::AddListEdit() и передача аргументом только строки, приводит к тому, что значениее isUppercase становится значением для isEditable в Class2::SetListEdit() и затем становится значением для isNumeric в Class1::SetEditBox().

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

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

Рефакторинг этого кода занял у меня 6 часов. Зато я избавился от переменных типа bool, заменил их единственным аргументом enum, так как в данном случае комбинации изначальных аргументов были между собой связаны логически. И теперь следующий разработчик сможет спокойно воспользоваться единственным нужным значением, вместо того, что бы смотреть где что установлено по умолчанию и что нужно прописать руками. Да и перебрать один аргумент через switch() гораздо легче, чем продираться через лес if()-ов для проверки всех возможных комбинаций для bool.

Округление дробей в стиле Omniva

Недавно получил от Omniva (бывшая Eesti Post) извещение о необходимости декларирования посылки на таможне.
Видимо, фирма сэкономила на тестировании софта, который генерирует такие извещения, особенно часть, где указывается вес посылки.
Думаю, что мне повезло, что посылка подлежащая декларированию не слишком тяжёлая и не слишком лёгкая, иначе, боюсь, получилось бы экспоненциальное форматирование.

Округление в стиле Omniva

320×480 ЖКИ на базе ILI9481 с сенсором прикосновения

До недавнего времени использовал в своих поделках текстовые ЖКИ или вынутые из мобильников.

Однако из Поднебесной доставили мне новый экранчик аж на 3.5 дюйма, с разрешением 320х480 пикселей и с сенсором прикосновения.

Экранчик работает от напряжения не более 3.3 вольта, поэтому при отсутствии конвертера логических уровней на 16 линий данных, мне пришлось отложить Ардуино в сторону и расчехлить Stellaris Launchpad.

Быстрое гугление дало понять, что экран на контроллере ILI9481 не новинка и уже множество готовых библиотек его поддерживает, включая замечательную UTFT. Как оказалось её уже успели портировать и для IDE Energia.

Так что не теряя времени даром, скачал библиотеку, установил и после небольшой запарки с подключением всех линий данных и управления (всего 24 провода), успешно запустил один из примеров.

Оживление маршрутизатора

Похоже было, что на моём Linksys WRT610N накрылась практически вся периферия (USB, Wi-Fi, WAN).

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

Когда он загрузился, перенастроил всё руками, не восстанавливая из бэкапа. Внезапно всё заработало как часы: и интернет, и USB и оба интерфейса Wi-Fi.

Немного пришлось пошерстить интернет, что бы вспомнить, как настраивался VPN, но и в конечном итоге он тоже заработал.

Подозреваю, что во всём этом безобразии всё же виновата схема питания маршрутизатора.

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

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

 

Домашний маршрутизатор помер

И теперь я без интернета.

Рутер давно уже странно себя вёл. В начале года безвозвратно отвалился второй Wi-Fi трансивер.

Сегодня полез было через VPN, но не тут то было. Проверил статус рутера, оказалось, что USB флэшка не примонтировалась.

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

Ребутнул рутер, так вообще отвалилось соединение с интернетом.

Думаю пока либо на процессор, либо на блок питания.

 

Сколько нужно айтишников, что бы повесить лампочку

Решил наконец поменять люстру в комнате.

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

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

Начал сверлить дырки под шурупы. Первая пошла удачно, а вот со второй оказалось всё сложно. С обратной стороны от крюка оказалась штукатурка 🙁

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

Пока отложил новую люстру в сторону и думаю над двумя вариантами:

  1. закрыть крюк и провода распределительной коробко, а люстру перенести в сторону
  2. закрыть место со штукатуркой, крюком и проводами какой-нибудь белой пластиной из дерева или пластика, а на пластину уже прицепить люстру.