Введение

Вставка данных в исходный код программы

Твердое кодирование (также жесткое кодирование или хардкодирование) — это практика разработки программного обеспечения, заключающаяся во внедрении данных непосредственно в исходный код программы или другого исполняемого объекта, в отличие от получения данных из внешних источников или их генерации во время выполнения. Данные, жестко закодированные таким образом, обычно можно изменить только путем редактирования исходного кода и повторной компиляции исполняемого файла, хотя их можно изменить в памяти или на диске с помощью отладчика или шестнадцатеричного редактора. Данные, жестко закодированные таким образом, лучше всего подходят для неизменяемой информации, такой как физические константы, номера версий и статические текстовые элементы. В отличие от этого, софтокодированные данные кодируют произвольную информацию посредством пользовательского ввода, текстовых файлов, INI-файлов, ответов HTTP-сервера, конфигурационных файлов, макросов препроцессора, внешних констант, баз данных и аргументов командной строки, и определяются во время выполнения.

Обзор

Жесткое кодирование требует изменения исходного кода программы каждый раз, когда изменяются входные данные или желаемый формат, в то время как конечному пользователю может быть удобнее изменять детали каким-либо способом вне программы. Жесткое кодирование часто необходимо, но также может рассматриваться как антипаттерн. Программисты могут еще не разработать динамическое решение пользовательского интерфейса для конечного пользователя, но при этом должны предоставить функциональность или выпустить программу. Обычно это временное решение, но в краткосрочной перспективе оно снимает давление, связанное с необходимостью сдать код. Впоследствии применяется softcoding, чтобы предоставить пользователю возможность передавать параметры, позволяющие конечному пользователю изменять результаты или итог. Термин "жестко закодированный" изначально использовался по аналогии с аппаратной схемой и должен был передать негибкость, возникающую при его использовании в проектировании и реализации программного обеспечения. В контексте сред совместной разработки с возможностью расширения во время выполнения, таких как MUD, жесткое кодирование также относится к разработке основного движка системы, отвечающего за задачи низкого уровня и выполнение скриптов, в отличие от softcoding, который заключается в разработке скриптов высокого уровня, интерпретируемых системой во время выполнения, с использованием значений из внешних источников, таких как текстовые файлы, INI-файлы, макросы препроцессора, внешние константы, базы данных, аргументы командной строки, ответы HTTP-сервера, файлы конфигурации и пользовательский ввод. В этом случае термин не имеет негативного оттенка и относится к общей разработке, а не к конкретному внедрению выходных данных.

Твердое кодирование и бэкдоры

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

Жесткое кодирование и DRM

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

Фиксированный путь установки

Если программа для Windows запрограммирована на предположение, что она всегда устанавливается в C:\Program Files\Appname, и кто-то попытается установить её на другой диск из-за нехватки места или соображений организации, установка может не выполниться или программа может не запуститься после установки. Эта проблема может остаться незамеченной в процессе тестирования, поскольку большинство пользователей устанавливают программы на диск и в каталог по умолчанию, а тестирование может не предусматривать возможность изменения каталога установки. Однако программистам и разработчикам не рекомендуется жёстко задавать путь установки программы, поскольку путь установки по умолчанию зависит от операционной системы, её версии и решений системного администратора. Например, во многих установках Microsoft Windows в качестве основного жесткого диска используется диск C:, но это не гарантировано. Схожая проблема существовала с микропроцессорами в первых компьютерах, которые начинали выполнение с фиксированного адреса в памяти.

Диск запуска

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

Специальные папки

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

Профильная дорожка

Некоторые программы Windows жёстко прописывают путь к профилю пользователя в предопределённые разработчиком места, например, C:\Documents and Settings\Username. Этот путь верен для большинства установок Windows 2000 и более поздних версий, но может привести к ошибке, если профиль хранится в сети или был перемещён в другое место. Правильный способ получения пути к профилю – использовать функцию GetUserProfileDirectory или разрешить переменную окружения %userprofile%. Другая распространённая ошибка разработчиков – предположение, что профиль пользователя находится на локальном жёстком диске.

Папка " Мои документы "

Некоторые программы Windows жестко прописывают путь к папке "Мои документы" как ProfilePath\My Documents. Эти программы будут работать на компьютерах с английской версией Windows, но в локализованных версиях Windows эта папка обычно имеет другое название. Например, в итальянской версии папка "Мои документы" называется Documenti. Кроме того, папку "Мои документы" могли переместить с помощью перенаправления папок в групповой политике, начиная с Windows 2000. Правильный способ получить путь к этой папке – использовать функцию SHGetFolderPath.

Решение

Косвенная ссылка, например, переменная внутри программы с именем "FileName", может быть расширена за счет доступа к диалоговому окну выбора файла, и код программы не потребуется изменять, если файл будет перемещен. Жесткое кодирование особенно проблематично при подготовке программного обеспечения к переводу на другие языки. Во многих случаях одно жестко заданное значение, такое как размер массива, может встречаться несколько раз в исходном коде программы. Это и есть "магическое число". Это может привести к ошибке в программе, если некоторые экземпляры этого значения будут изменены, но не все. Обнаружить такую ошибку сложно, и она может оставаться в программе длительное время. Аналогичная проблема может возникнуть, если одно и то же жестко заданное значение используется для нескольких параметров, например, для массива из 6 элементов и минимальной длины входной строки в 6 символов. Программист может ошибочно изменить все экземпляры этого значения (часто с помощью функции поиска и замены в редакторе), не проверяя, как используется каждый из них. Обеих ситуаций можно избежать, определяя константы, которые связывают имена со значениями, и используя имена констант при каждом упоминании в коде. Важным случаем жесткого кодирования является непосредственное размещение строк в файле, что вынуждает переводчиков редактировать исходный код для перевода программы. (Существует инструмент gettext, который позволяет оставлять строки в файлах, но дает переводчикам возможность переводить их без изменения исходного кода, фактически избавляя от жесткого кодирования строк.)

Твердое кодирование в конкурсах

В соревнованиях по программированию, таких как Международная олимпиада по информатике, участники должны написать программу с заданным форматом ввода-вывода, соответствующим условиям задач. В редких случаях, когда количество возможных входных данных достаточно мало, участник может рассмотреть подход, который сопоставляет все возможные входные данные с их правильными выходными данными. Такая программа будет считаться "жестко закодированным" решением, в отличие от алгоритмического (хотя жестко закодированная программа может быть результатом работы алгоритмической программы).

Мягкое кодирование

Softcoding – это термин в программировании, обозначающий получение значения или функции из внешнего источника, такого как текстовые файлы, INI-файлы, макросы препроцессора, внешние константы, файлы конфигурации, аргументы командной строки, базы данных, пользовательский ввод или ответы HTTP-сервера. Это противоположность жесткому кодированию (hardcoding), при котором значения и функции непосредственно записываются в исходный код.

Практика программирования

Избегать жесткого кодирования часто изменяемых значений – хорошая практика программирования. Пользователи программного обеспечения должны иметь возможность настраивать его под свои нужды, в разумных пределах, без необходимости редактировать исходный код программы. Аналогично, внимательные программисты избегают использования "магических чисел" в коде, чтобы повысить его читаемость и облегчить поддержку. Эти приемы обычно не называют "мягким кодированием". Термин "мягкое кодирование" обычно применяется, когда оно превращается в антипаттерн. Чрезмерная абстракция значений и функций может привести к большей сложности и проблемам с поддержкой, чем внесение изменений в код при необходимости. "Мягкое кодирование" в этом смысле было описано в статье на The Daily WTF.

Потенциальные проблемы

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

Достижение гибкости

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