Если проанализировать историю программных и аппаратных архитектур, программных продуктов и парадигм программирования, то можно найти различия в подходах реализации хранения данных обработки и программных кодов.
Идеи, основанные на автоматном программировании, явно разделяют инструкции и память. Самые известные примеры автоматного программирования – это машина Тьюринга и машина Поста.
Аналогичная ситуация складывается и с продукционным программированием (нормальные алгоритмы Маркова). Продукции описываются одной структурой, а операционные данные рассматриваются как другая структура. Функциональное программирование (лямбда-исчисление) также разделяет описательную и операционную часть.
Ещё в 1946 году фон Нейманом при проектировании первых процессоров были сформированы несколько принципов построения ЭВМ. Одним из его принципов был принцип однородности памяти, в котором говорилось, что программы и данные хранятся в одной и той же памяти. С командами можно выполнять такие же действия, как и с данными. Альтернативой фон Неймановской архитектуре является гарвардская архитектура, которую отличает раздельное хранение команд и данных.
В практическом применении процессоры в начальной стадии развития разделяли общую область памяти на отдельные сегменты. В одном сегменте хранились управляющие данные, то есть коды команд, другой сегмент был областью памяти для хранения операционных данных. С развитием архитектуры процессоров для защиты программы от некорректных операций и, следовательно, для поддержания целостности управляющих инструкций процессора (команд), сам процессор контролировал область памяти с программным кодом и не позволял записывать в нее какие-либо значения.
В высокоуровневых языках программирования транслятор обычно ограничивает доступ к памяти, где хранится исполняемый код, а в интерпретируемых языках и вовсе отсутствует возможность не то, что скорректировать текст программы, но и даже получить этот текст. Одним из исключений является инструкция List некоторых реализаций языка программирования Basic, выводящая на экран исходный код программы. В других языках программирования для этих целей специально придумывают специальные программы, называемые « квайн» ( quine). Аналогично, в скриптовых языках типа bat-файлов в dos/windows и *sh в Unix-системах код существует в текстовых файлах, а соответственно и доступ к ним может осуществляться через операции с файлами. В части языков программирования такая возможность реализуется через возможности интерпретатора или p-кода (пи-кода).
Другим исключением является операции аналогичного вида со встраиваемыми языками и скриптами. Первые – это SDK VBA, которые позволяют вызывать интерпретируемые VBA-процедуры из программного кода и скрипты обычно относятся к собственным языкам программирования либо тому же интерпретируемому языку программирование (как, например, команда exec в T-SQL и eval () в PHP).
Но фактически эти возможности остаются невостребованными с точки зрения модификации кода.
Говоря о различии между программным кодом и данными, нельзя забывать, что и программный код содержит данные.
Строгое разделение данных и программной обработки данных влияет и на целостность самих данных. В частности, программный код содержит константы, которые ссылаются на данные в хранилище данных, в том числе в СУБД. Данные со временем могут меняться, в то время как ссылки на них остаются неизменными. Часто эти ссылки невозможно отследить, что является потенциальным источником ошибок как результат несогласованности между данными внутри программного кода и данными в хранилище данных, что называется нарушением логической целостности данных.
Например, мы настраиваем финансовый отчет на основании оборотов по продажам и затратам. В программном коде отчета мы жестко привязываемся к счету плана счетов «Затраты на командировки», чтобы по этому конкретному коду счета настроить отчет, собирающий финансовые проводки из главной книги. В результате, если в дальнейшем потребуется изменить план счетов, например, изменить код для счета «затраты на командировки» либо создать дополнительный счёт с новым кодом для этих же целей, то отчет не будет работать так, как нужно – не будет работать вовсе либо будет работать частично по используемой ранее более узкой логике.
С одной стороны, вместо определения константы с кодом мы можем брать его из отдельного справочника или элемента данных, привязанного к плану счетов. Но с другой стороны, мы не можем это сделать, поскольку структура данных является фиксированной, а, кроме того, в таком случае нас ждёт сложная процедура администрирования этих структур, включая организацию ссылки на план счетов, массовых данных при необходимости (например, вместо одного счета мы должны указывать ряд счетов) и визуализации данных. Такой комплекс процедур влечет за собой существенные накладные расходы при настройке отчета, поэтому от этого пути отказываются в пользу отказа от контроля над целостностью данных.
Читать дальше