Программирование → Генерация списка IPv4 адресов на TCL и немного систем счисления
Не так давно потребовалось решать задачу массового обновления конфигурации устройств. Стандартная задача системного администрирования, если у вас в обслуживании больше одного устройства выполняющего однотипные функции. Для решения существуют как универсальные продукты, например из доступных redmine.nocproject.org, так и множество скриптов широко представленных на тематических форумах и порталах. Как раз на этот случай под рукой и должен был оказаться собственный написанный скрипт, но не оказался, поэтому учитывая что время для манёвров было, скрипт был написан заново, выполнен и положен на полочку, чтобы там в очередной раз затеряться.
Для написания был использован expect — expect.sourceforge.net, надстройка над TCL позволяющая обрабатывать и реагировать на ответы различных интерактивных консольных утилит, в частности, telnet. Учитывая что для TCL раньше писать не приходилось, код нуждался в повторном осмыслении. Ключевой момент скрипта это генератор списка IPv4 адресов для обработки, после внимательной оценки данный кусок программы удалось значительно, на мой взгляд, оптимизировать, по крайней мере сократить количество строк на треть и безболезненно добавить новый функционал. Причём все эти сокращения мало относились к специфики TCL, а касались принципиальных подходов к построению алгоритма в целом.
Я выделил этот код в отдельную утилиту, которую попытаюсь очень подробно разобрать далее по тексту — как было «до» и что стало «после», и почему не получилось написать сразу так как «после». Мне не всё в ней нравится до сих пор: смущают как алгоритмические проблемы так и проблемы TCL, например использование списков вместо массивов (что быстрее?, безопаснее?, идеологически вернее?), все сомнения тоже присутствуют в тексте, с надеждой на конструктивные комментарии.
Для написания был использован expect — expect.sourceforge.net, надстройка над TCL позволяющая обрабатывать и реагировать на ответы различных интерактивных консольных утилит, в частности, telnet. Учитывая что для TCL раньше писать не приходилось, код нуждался в повторном осмыслении. Ключевой момент скрипта это генератор списка IPv4 адресов для обработки, после внимательной оценки данный кусок программы удалось значительно, на мой взгляд, оптимизировать, по крайней мере сократить количество строк на треть и безболезненно добавить новый функционал. Причём все эти сокращения мало относились к специфики TCL, а касались принципиальных подходов к построению алгоритма в целом.
Я выделил этот код в отдельную утилиту, которую попытаюсь очень подробно разобрать далее по тексту — как было «до» и что стало «после», и почему не получилось написать сразу так как «после». Мне не всё в ней нравится до сих пор: смущают как алгоритмические проблемы так и проблемы TCL, например использование списков вместо массивов (что быстрее?, безопаснее?, идеологически вернее?), все сомнения тоже присутствуют в тексте, с надеждой на конструктивные комментарии.
Разработка → Читайте код, с остальным справится компилятор
Введение
Уже не в первый раз мне задают связанные вопросы:
«Зачем ты делаешь так много функций?»;
«Зачем ты выносишь, однократно используемый, код в функции?»;
«Остальные не знакомы с твоими правилами именования функций. Как они будут с этим работать?». Поэтому опишу свое видение проблемы. Ну а сообщество подскажет, к чему же стоит стремиться.
Проектирование и рефакторинг → Объектно-ориентированная разработка инсталлятора Gin
Ссылка на первую часть
Ссылка на вторую часть
Ссылка на третью часть
Любой инсталлятор должен давать пользователю возможность вводить некоторые стартовый параметры, например, путь к папке, куда будет инсталлирована программа, строка подключения к базе данных, и т.д. Причем, хотелось бы, чтобы это были не просто текстовые поля, а поля, дающие возможность удобного вода данных. Если это путь установки программы, то помимо текстового поля должна быть кнопка «Browse…», если это строка подключения к БД, то пусть рядом будет кнопка для выбора или создания источника данных и т.д.
Ссылка на вторую часть
Ссылка на третью часть
Ввод данных
Любой инсталлятор должен давать пользователю возможность вводить некоторые стартовый параметры, например, путь к папке, куда будет инсталлирована программа, строка подключения к базе данных, и т.д. Причем, хотелось бы, чтобы это были не просто текстовые поля, а поля, дающие возможность удобного вода данных. Если это путь установки программы, то помимо текстового поля должна быть кнопка «Browse…», если это строка подключения к БД, то пусть рядом будет кнопка для выбора или создания источника данных и т.д.
Проектирование и рефакторинг → Объектно-ориентированная разработка инсталлятора Gin
Ссылка на первую часть
Ссылка на вторую часть
Некоторые команды подразумевают работу с файлами, изначально хранимыми на компьютере разработчика пакета. Понятно, что эти файлы нужно вместе с пакетом (а желательно, прямо внутри пакета) доставить к потребителю пакета. Попробуем для начала представить себе как это будет работать.
У нас есть экземпляр класса PackageBuilder, которому при конструировании мы указываем аргумент PackageBody, содержащий в себе, помимо всего прочего, команду Command, которая представляет собой корневой узел дерева команд пакета. Метод SaveResult() экземпляра класса PackageBuilder должен рекурсивно обойти все дерево, и для тех команд, которые используют контентные файлы, расположенные на компьютере разработчика, включить в тело пакета содержимое всех этих файлов. В тело пакета он также должен включить xml-файл, в который будет сериализован сам PackageBody с полным описанием пакета и выполняемых им команд.
Ссылка на вторую часть
Контентные и контейнерные команды
Некоторые команды подразумевают работу с файлами, изначально хранимыми на компьютере разработчика пакета. Понятно, что эти файлы нужно вместе с пакетом (а желательно, прямо внутри пакета) доставить к потребителю пакета. Попробуем для начала представить себе как это будет работать.
У нас есть экземпляр класса PackageBuilder, которому при конструировании мы указываем аргумент PackageBody, содержащий в себе, помимо всего прочего, команду Command, которая представляет собой корневой узел дерева команд пакета. Метод SaveResult() экземпляра класса PackageBuilder должен рекурсивно обойти все дерево, и для тех команд, которые используют контентные файлы, расположенные на компьютере разработчика, включить в тело пакета содержимое всех этих файлов. В тело пакета он также должен включить xml-файл, в который будет сериализован сам PackageBody с полным описанием пакета и выполняемых им команд.
Проектирование и рефакторинг → Объектно-ориентированная разработка инсталлятора Gin
Ссылка на первую часть
Напомню, что я собирался реализовать механизм транзакций, позволяющий откатывать блоки операций при возникновении ошибки внутри блока, защищенного транзакцией. Сначала надо решить вопрос с ответственностью за сохранение состояния и за откат операции. Скажу сразу, что архитектура, которую я приведу ниже вырисовалась у меня не сразу, а только после нескольких попыток проектирования и реализации макета, пока у меня не получилось то, что получилось.
Для того, чтобы архитектура транзакций была легко наращиваемой, воспользуемся как и ранее наследованием. При этом возложим ответственность за сохранение состояние и откат к сохраненному состоянию на саму команду. Учтем при этом, что не все команды являются по сути транзакционными. Например, чтение из реестра не может быть частью транзакции, потому что оно ничего не изменяет в системе. А вот запись в реестр – это уже часть транзакции. И создание файла – это часть транзакции.
А поэтому объявим еще один абстрактный класс TransactionalCommand, унаследуем его от класса Command.
Транзакции.
Напомню, что я собирался реализовать механизм транзакций, позволяющий откатывать блоки операций при возникновении ошибки внутри блока, защищенного транзакцией. Сначала надо решить вопрос с ответственностью за сохранение состояния и за откат операции. Скажу сразу, что архитектура, которую я приведу ниже вырисовалась у меня не сразу, а только после нескольких попыток проектирования и реализации макета, пока у меня не получилось то, что получилось.
Для того, чтобы архитектура транзакций была легко наращиваемой, воспользуемся как и ранее наследованием. При этом возложим ответственность за сохранение состояние и откат к сохраненному состоянию на саму команду. Учтем при этом, что не все команды являются по сути транзакционными. Например, чтение из реестра не может быть частью транзакции, потому что оно ничего не изменяет в системе. А вот запись в реестр – это уже часть транзакции. И создание файла – это часть транзакции.
А поэтому объявим еще один абстрактный класс TransactionalCommand, унаследуем его от класса Command.
Проектирование и рефакторинг → Объектно-ориентированная разработка инсталлятора Gin из песочницы
Введение
У предлагаемого вашему вниманию цикла статей есть несколько основных целей:
- Создать полезное программное обеспечение – инсталлятор программ и обновлений.
- Показать преимущества объектно-ориентированного подхода к разработке ПО и научить создавать легко расширяемые программные архитектуры.
В данном цикле статей я хочу поделиться историей создания программного обеспечения, позволяющего производить установку и обновление программных продуктов компании при помощи пакетов. Необходимость создания собственного инсталлятора(с отказом от использования готовых решений) вызвана специфичностью требований к инсталлятору. Я не буду углубляться в обоснование необходимости разработки, так как тема цикла статей другая.
Основными требованиями к разрабатываемой архитектуре будут:
- Реализация механизма транзакций, причем транзакции могут включать в себя не только SQL-транзакции, но и файловые, а также транзакции, связанные с изменением любых других ресурсов ОС, таких как записи в реестре, изменения конфигурационных файлов и т.д.
- Расширяемость операционной базы инсталлятора, то есть, добавление новых типов команд(операций), как с поддержкой транзакций, так и без нее.
PHP → Внедряем namespace в существующий php-код
Увидел статью о namespace и решил поделиться опытом перевода существующих проектов на namespace.
В основном статья будет полезна тем, кто еще не использует namespace, но задумывается над переписыванием существующего кода.
Я переводил на namespace несколько своих проектов, которые были взаимосвязаны между собой. Проекты не слишком большие и весь переход я сделал за выходные.
Сам по себе переход не представляет особых проблем, ниже я описал последовательность необходимых действий, которые в большинстве своем представляют собой рутину и имеется возможность автоматизации большей части работ… но как говорится дъявол кроется в деталях.
В основном статья будет полезна тем, кто еще не использует namespace, но задумывается над переписыванием существующего кода.
Я переводил на namespace несколько своих проектов, которые были взаимосвязаны между собой. Проекты не слишком большие и весь переход я сделал за выходные.
Сам по себе переход не представляет особых проблем, ниже я описал последовательность необходимых действий, которые в большинстве своем представляют собой рутину и имеется возможность автоматизации большей части работ… но как говорится дъявол кроется в деталях.
C++ → Про абстракции и метод рефакторинга «Extract method» из песочницы
Абстракции чрезвычайно важны в программировании и это все знают. Они помогают нам отделить существенные детали чего бы то ни было от несущественных. В идеале они должны выделять только самое главное, эссенцию, без всяких посторонних примесей, минимум характеристик объекта или процесса, но идеал встречается не так уж и часто.