---
title: "Жёсткое кодирование"
type: "antipattern"
slug: "hard-coding"
url: "http://localhost:3000/ru/antipatterns/hard-coding.md"
description: "Размещение данных в исходном коде программы"
---
# Жёсткое кодирование

> Размещение данных в исходном коде программы

**Жёсткое кодирование** — это практика разработки программного обеспечения, при которой данные встраиваются непосредственно в [исходный код](https://en.wikipedia.org/wiki/Source%5Fcode "Source code") [программы](https://en.wikipedia.org/wiki/Computer%5Fprogram "Computer program") или другого исполняемого объекта, в отличие от получения данных из внешних источников или их генерации во [время выполнения](https://en.wikipedia.org/wiki/Run%5Ftime%5F%28program%5Flifecycle%5Fphase%29 "Run time (program lifecycle phase)").

Жёстко закодированные данные обычно можно изменить только путём редактирования исходного кода и [повторной компиляции](https://en.wikipedia.org/wiki/Compiling "Compiling") исполняемого файла, хотя их можно изменить в [памяти](https://en.wikipedia.org/wiki/Volatile%5Fmemory "Volatile memory") или на диске с помощью [отладчика](https://en.wikipedia.org/wiki/Debugger "Debugger") или [шестнадцатеричного редактора](https://en.wikipedia.org/wiki/Hex%5Feditor "Hex editor").

Жёстко закодированные данные лучше всего подходят для неизменяемых фрагментов информации, таких как [физические константы](https://en.wikipedia.org/wiki/Physical%5Fconstant "Physical constant"), [номера версий](https://en.wikipedia.org/wiki/Version%5Fnumber "Version number") и статические текстовые элементы.

Мягко закодированные данные, напротив, кодируют произвольную информацию через [пользовательский ввод](https://en.wikipedia.org/wiki/User%5Finput "User input"), [текстовые файлы](https://en.wikipedia.org/wiki/Text%5Ffiles "Text files"), [INI-файлы](https://en.wikipedia.org/wiki/INI%5Ffile "INI file"), ответы HTTP-сервера, файлы конфигурации, макросы препроцессора, внешние константы, базы данных, [аргументы командной строки](https://en.wikipedia.org/wiki/Command-line%5Fargument "Command-line argument") и определяются во время выполнения.

## Обзор

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

Жёсткое кодирование часто необходимо, но может также рассматриваться как [антипаттерн](https://en.wikipedia.org/wiki/Anti-pattern "Anti-pattern"). Возможно, у программистов ещё не проработано решение с динамическим пользовательским интерфейсом для конечного пользователя, но им всё равно нужно реализовать функцию или выпустить программу. Обычно это временно, но в краткосрочной перспективе снимает давление, связанное с необходимостью сдать код. Позднее выполняется мягкое кодирование, чтобы позволить пользователю передавать параметры, дающие конечному пользователю способ изменять результаты.

Термин «жёстко закодированный» изначально использовался по аналогии с жёсткой коммутацией электрических цепей и был призван передать негибкость, возникающую при его применении в проектировании и реализации программного обеспечения. В контексте расширяемых во время выполнения [сред совместной разработки](https://en.wikipedia.org/wiki/Collaborative%5Fdevelopment%5Fenvironment "Collaborative development environment"), таких как [MUD](https://en.wikipedia.org/wiki/Multi-user%5Fdungeon "Multi-user dungeon"), жёсткое кодирование также означает разработку ядра системы, отвечающего за низкоуровневые задачи и выполнение [скриптов](https://en.wikipedia.org/wiki/Scripting%5Flanguage "Scripting language"), в отличие от **мягкого кодирования**, представляющего собой разработку высокоуровневых скриптов, которые интерпретируются системой во [время выполнения](https://en.wikipedia.org/wiki/Execution%5F%28computing%29 "Execution (computing)"), со значениями из внешних источников, таких как [текстовые файлы](https://en.wikipedia.org/wiki/Text%5Ffiles "Text files"), [INI-файлы](https://en.wikipedia.org/wiki/INI%5Ffile "INI file"), [макросы](https://en.wikipedia.org/wiki/Macro%5F%28computer%5Fscience%29 "Macro (computer science)") препроцессора, внешние константы, [базы данных](https://en.wikipedia.org/wiki/Database "Database"), [аргументы командной строки](https://en.wikipedia.org/wiki/Command-line%5Fargument "Command-line argument"), ответы [HTTP](https://en.wikipedia.org/wiki/HTTP "HTTP")\-[сервера](https://en.wikipedia.org/wiki/Server%5F%28computing%29 "Server (computing)"), [файлы конфигурации](https://en.wikipedia.org/wiki/Configuration%5Ffile "Configuration file") и [пользовательский ввод](https://en.wikipedia.org/wiki/User%5Finput "User input"). В этом случае термин не имеет уничижительного оттенка и относится к разработке в целом, а не конкретно к встраиванию выходных данных.

## Бэкдоры

Жёсткое кодирование учётных данных — популярный способ создания [бэкдора](https://en.wikipedia.org/wiki/Backdoor%5F%28computing%29 "Backdoor (computing)"). Жёстко закодированные учётные данные обычно не видны в файлах конфигурации или в выводе команд перечисления учётных записей и не могут быть легко изменены или обойдены пользователями. В случае обнаружения пользователь может отключить такой бэкдор, изменив и пересобрав программу из её [исходного кода](https://en.wikipedia.org/wiki/Source%5Fcode "Source code") ([если исходный код общедоступен](https://en.wikipedia.org/wiki/FLOSS "FLOSS")), путём [декомпиляции](https://en.wikipedia.org/wiki/Decompiling "Decompiling") или [обратной разработки](https://en.wikipedia.org/wiki/Reverse-engineering "Reverse-engineering") [программного обеспечения](https://en.wikipedia.org/wiki/Software "Software"), [прямого редактирования](https://en.wikipedia.org/wiki/Hex%5Feditor "Hex editor") [двоичного кода](https://en.wikipedia.org/wiki/Binary%5Fcode "Binary code") программы или внедрения проверки целостности (такой как цифровые подписи, защита от взлома и [защита от читерства](https://en.wikipedia.org/wiki/Anti-cheat "Anti-cheat")) для предотвращения непредвиденного доступа, однако такие действия часто запрещены [лицензионным соглашением с конечным пользователем](https://en.wikipedia.org/wiki/End-user%5Flicense%5Fagreement "End-user license agreement").

## Управление цифровыми правами

В качестве меры [управления цифровыми правами](https://en.wikipedia.org/wiki/Digital%5Frights%5Fmanagement "Digital rights management") (DRM) разработчики программного обеспечения могут жёстко закодировать уникальный [серийный номер](https://en.wikipedia.org/wiki/Serial%5Fnumber "Serial number") непосредственно в программу. Также распространено жёсткое кодирование [открытого ключа](https://en.wikipedia.org/wiki/Public%5Fkey "Public key"), что создаёт DRM, для которого невозможно создать генератор ключей.

В противоположном случае [взломщик программного обеспечения](https://en.wikipedia.org/wiki/Software%5Fcracker "Software cracker") может жёстко закодировать действительный серийный номер в программу или даже не дать исполняемому файлу запрашивать его у пользователя, что позволяет распространять несанкционированные копии без необходимости вводить действительный номер, используя таким образом один и тот же ключ для каждой копии, если он был жёстко закодирован.

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

Если программа для Windows запрограммирована исходить из того, что она всегда устанавливается в C:\\Program Files\\Appname и кто-то пытается установить её на другой диск из соображений места или организации, она может не установиться или не запуститься после установки. Эта проблема может не выявиться в процессе тестирования, поскольку средний пользователь устанавливает на диск и в каталог по умолчанию, а тестирование может не включать вариант изменения каталога установки. Тем не менее программистам и разработчикам рекомендуется не фиксировать путь установки программы, поскольку путь установки по умолчанию зависит от операционной системы, её версии и решений [системного администратора](https://en.wikipedia.org/wiki/Sysadmin "Sysadmin"). Например, многие установки [Microsoft Windows](https://en.wikipedia.org/wiki/Microsoft%5FWindows "Microsoft Windows") используют [диск C:](https://en.wikipedia.org/wiki/Drive%5Fletter%5Fassignment#Common%5Fassignments "Drive letter assignment") в качестве основного [жёсткого диска](https://en.wikipedia.org/wiki/Hard%5Fdisk "Hard disk"), но это не гарантируется.

Похожая проблема была с [микропроцессорами](https://en.wikipedia.org/wiki/Microprocessor "Microprocessor") в ранних компьютерах, которые [начинали выполнение](https://en.wikipedia.org/wiki/Reset%5F%28computing%29 "Reset (computing)") по фиксированному [адресу](https://en.wikipedia.org/wiki/Address%5Fspace "Address space") в памяти.

## Загрузочный диск

Некоторые «[защищённые от копирования](https://en.wikipedia.org/wiki/Copy%5Fprotection "Copy protection")» программы при запуске ищут определённый файл на [дискете](https://en.wikipedia.org/wiki/Floppy%5Fdisk "Floppy disk") или флеш-накопителе, чтобы убедиться, что они не являются несанкционированными копиями. Если компьютер заменяется более новой машиной без дисковода для дискет, программа, которая его требует, теперь не может быть запущена, поскольку дискету невозможно вставить.

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

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

Некоторые операционные системы Windows имеют так называемые [специальные папки](https://en.wikipedia.org/wiki/Special%5Ffolders "Special folders"), которые логически упорядочивают файлы на жёстком диске. При жёстком кодировании могут возникать следующие проблемы:

### Путь к профилю

Некоторые программы Windows жёстко кодируют путь к профилю в заданные разработчиком расположения, такие как `C:\Documents and Settings\_Username_`. Это путь для подавляющего большинства [Windows 2000](https://en.wikipedia.org/wiki/Windows%5F2000 "Windows 2000") и выше, но он вызвал бы ошибку, если профиль хранится в сети или иным образом перемещён. Правильный способ получить его — вызвать функцию `GetUserProfileDirectory` или развернуть [переменную окружения](https://en.wikipedia.org/wiki/Environment%5Fvariable "Environment variable") `%userprofile%`. Ещё одно предположение, которое часто делают разработчики, — что профиль находится на локальном жёстком диске.

### Путь к папке «Мои документы»

Некоторые программы Windows жёстко кодируют путь к `[Мои документы](https://en.wikipedia.org/wiki/My%5FDocuments "My Documents")` как `_ProfilePath_\My Documents`. Эти программы работали бы на машинах с английской версией, но на [локализованных](https://en.wikipedia.org/wiki/Internationalization%5Fand%5Flocalization "Internationalization and localization") версиях Windows эта папка обычно имеет другое имя. Например, в итальянских версиях папка `My Documents` называется _Documenti_. `My Documents` также может быть перемещена с помощью перенаправления папок в [групповой политике](https://en.wikipedia.org/wiki/Group%5FPolicy "Group Policy") в Windows 2000 и выше. Правильный способ получить её — вызвать функцию `SHGetFolderPath`.

## Решение

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

Жёсткое кодирование особенно проблематично при подготовке программного обеспечения к переводу на другие языки.

Во многих случаях одно жёстко закодированное значение, например размер массива, может встречаться несколько раз в исходном коде программы. Это было бы [магическим числом](https://en.wikipedia.org/wiki/Magic%5Fnumber%5F%28programming%29 "Magic number (programming)"). Это часто может приводить к ошибке в программе, если некоторые из вхождений значения изменены, а другие — нет. Такую ошибку трудно найти, и она может долго оставаться в программе. Похожая проблема может возникнуть, если одно и то же жёстко закодированное значение используется более чем для одного параметра, например массив из 6 элементов и минимальная длина входной строки 6\. Программист может по ошибке изменить все вхождения значения (часто с помощью функции поиска и замены в редакторе), не проверив код, чтобы понять, как используется каждое вхождение. Обеих ситуаций можно избежать, определив [константы](https://en.wikipedia.org/wiki/Constant%5F%28programming%29 "Constant (programming)"), которые связывают имена со значениями, и используя имена констант для каждого вхождения в коде.

Один важный случай жёсткого кодирования — когда строки помещаются непосредственно в файл, что вынуждает переводчиков редактировать исходный код для перевода программы. (Существует инструмент под названием `[gettext](https://en.wikipedia.org/wiki/Gettext "Gettext")`, который позволяет оставлять строки в файлах, но даёт переводчикам возможность переводить их без изменения исходного кода; по сути, он отменяет жёсткое кодирование строк.)

## Соревнования по программированию

В соревнованиях по программированию, таких как [Международная олимпиада по информатике](https://en.wikipedia.org/wiki/International%5FOlympiad%5Fin%5FInformatics "International Olympiad in Informatics"), участники должны написать программу с определённым шаблоном ввода-вывода в соответствии с требованиями заданий.

В редких случаях, когда возможное число входных данных достаточно мало, участник может рассмотреть подход, сопоставляющий все возможные входные данные с их правильными выходными данными. Такая программа считалась бы жёстко закодированным решением в противоположность [алгоритмическому](https://en.wikipedia.org/wiki/Algorithm "Algorithm") (даже если жёстко закодированная программа может быть результатом работы алгоритмической программы).

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

**Мягкое кодирование** — это термин [программирования](https://en.wikipedia.org/wiki/Computer%5Fcoding "Computer coding"), обозначающий получение значения или функции из какого-либо внешнего ресурса, такого как [текстовые файлы](https://en.wikipedia.org/wiki/Text%5Ffiles "Text files"), [INI-файлы](https://en.wikipedia.org/wiki/INI%5Ffile "INI file"), [макросы](https://en.wikipedia.org/wiki/Macro%5F%28computer%5Fscience%29 "Macro (computer science)") [препроцессора](https://en.wikipedia.org/wiki/Preprocessor "Preprocessor"), внешние константы, [файлы конфигурации](https://en.wikipedia.org/wiki/Configuration%5Ffile "Configuration file"), [аргументы командной строки](https://en.wikipedia.org/wiki/Command-line%5Fargument "Command-line argument"), базы данных, пользовательский ввод, ответы HTTP-сервера. Это противоположность жёсткого кодирования, которое означает кодирование значений и функций в исходном коде.

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

Избегание жёсткого кодирования часто изменяемых значений — хорошая практика программирования. Пользователи программного обеспечения должны иметь возможность в разумных пределах настраивать его под свои нужды, не редактируя исходный код программы. Аналогично, аккуратные программисты избегают [магических чисел](https://en.wikipedia.org/wiki/Magic%5Fnumber%5F%28programming%29#Unnamed%5Fnumerical%5Fconstants "Magic number (programming)") в своём коде, чтобы повысить его читаемость и облегчить сопровождение. Эти практики обычно не называют _мягким кодированием_.

Термин обычно используется там, где мягкое кодирование становится [антипаттерном](https://en.wikipedia.org/wiki/Anti-pattern "Anti-pattern"). Вынесение в абстракцию слишком большого числа значений и возможностей может вносить больше сложности и проблем с сопровождением, чем изменение кода при необходимости. Мягкое кодирование в этом смысле было описано в статье на [The Daily WTF](https://en.wikipedia.org/wiki/The%5FDaily%5FWTF "The Daily WTF").

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

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

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

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

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

Существует несколько обоснованных паттернов проектирования для достижения гибкости, которую пытается обеспечить мягкое кодирование. Приложению, требующему большей гибкости, чем уместно для файла конфигурации, может пойти на пользу включение [скриптового языка](https://en.wikipedia.org/wiki/Scripting%5Flanguage "Scripting language"). Во многих случаях подходящим решением является [предметно-ориентированный язык](https://en.wikipedia.org/wiki/Domain-specific%5Flanguage "Domain-specific language"), интегрированный в устоявшийся скриптовый язык. Другой подход — перенести большую часть функциональности приложения в библиотеку, предоставив API для быстрого написания связанных приложений.
