Что общего между принципами программирования и геномом?
Такую неожиданную аналогию я увидел, когда читал книгу «Рождение сложности. Эволюционная биология сегодня» Александра Маркова.
Прежде всего хочу, чтобы вы вспомнили или же узнали один из фундаментальных принципов, на котором держится вся ДНК-жизнь на земле. Это комплементарность.
Вот определение из википедии: Комплемента́рность (в химии, молекулярной биологии и генетике) — взаимное соответствие молекул биополимеров или их фрагментов, обеспечивающее образование связей между пространственно взаимодополняющими (комплементарными) фрагментами молекул или их структурных фрагментов вследствие супрамолекулярных взаимодействий (образование водородных связей, гидрофобных взаимодействий, электростатических взаимодействий заряженных функциональных групп и т. п.).
Причем, эта связь не сопровождается образованием ковалентной химической связи, но благодаря пространственному соответствию больших молекул они образуют множество слабых водородных связей. Грубо говоря, это детали лего-конструктора, которые по одиночке очень легко разделить, но если слепить несколько сотен кубиков, то это уже довольно прочная конструкция, особенно если обеспечить соответствующие замыкающие элементы.
В состав любой молекулы ДНК входит всего лишь четыре азотистых основания А, Ц, Т, Г. Затем они комбинируются друг с другом в самых причудливых сочетаниях, и в результате мы получаем ДНК любого живого существа на Земле!
Теперь посмотрим, есть ли в программировании нечто подобное? Многие, конечно, знают, что в основе работы цифровой техники заложена бинарная логика в силу того, что мы можем различными комбинациями всего лишь двух значений, закодировать любое состояние. Ученые даже придумали специальную булеву алгебру. Не вдаваясь в подробности, там имеются всего лишь три операции И, ИЛИ, НЕ над выделенными элементами 0 и 1. И этого хватает, чтобы ваш компьютер был способен производить все свои операции. Не важно чем вы занимаетесь: играете в игры, пишите в текстовом редакторе, рисуете или генерируете картинку с помощью ИИ, все эти действия возможны благодаря бесчисленному хитрому перекомбинированию нулей и единиц с помощью ТРЁХ операций!
Теперь попробуем выделить аналогии между эволюцией животных и теорией программирования.
Эволюция
Основная теория эволюционного развития живого из неживого сейчас строиться на том, что когда-то простые химические реакции окисления с помощью катализаторов получили большую силу и в результате смогли протекать быстрее.
Миллионы лет где-то возле безжизненных гейзеров варился суп из целой кучи химических веществ, которые вступали между собой в реакцию. Когда там появлялись молекулы катализаторов, тогда реакции протекали быстрее. Постепенно быстрые реакции смогли формировать в результате своей деятельности причудливые соединения, просто потому-то в супе их было предостаточно. Вот эти соединения в себе уже имели катализаторы в качестве захваченных элементов при окислении. В какой-то момент молекулы получались настолько удачно сформированы, что они смогли вокруг себя производить еще больше реакции и формировать подобные себе остатки от окисления. Т.е. удачная случайная комбинация «сгорания» одних веществ заставляла превращалась в собственный катализатор и благодаря этому налаживала процесс «сгорания» таким образом, что в результате получалось еще больше подобных катализаторов.
Вот так миллиард лет (а это очень много) формировались первые прототипы РНК, состоящие из кирпичиков А, Ц, Т, Г. Они уже могли не просто инициировать усиленные реакции вокруг себя, но начать целенаправленный процесс дублирования себе подобных.
Затем выяснилось, что если РНК сможет в процессе «горения» образовать вокруг себя некую оболочку, то с большой долей вероятности эта комбинация РНК сможет дольше позволить себе процесс дублирования. Хотя оболочка — это лишь случайный продукт реакции, которая закрепилась за удачными РНК-старателями. Факт того, что они смогли выжить и продолжить это – закрепил данный признак.
Природа в процессе развития жизни эволюционным путём находила удачные принципы комбинации составных частей. Причём чем более защищённой и энерго-эффективней получалась конструкция, тем с большей вероятностью она повторялась будущими поколениями. Сначала это были археи и простейшие безъядерные бактерии. Они представляли из себя обособленные капельки, окруженные оболочкой, которые могли пропускать в себя полезные вещества для химических реакций, а когда материала становилось больше, то они делились пополам. Это очень упрощенная картина, но суть примерно такая.
Вся наследственная информация складывается в геном. Причём и тут есть интересная особенность, геном напрямую кодирует только строение одной клетки. А как же цвет глаз, ноги, крылья и хвосты, спросите вы? Тут снова действует закон сложных систем. Даже если две клетки находятся по соседству друг с другом, то они могут влиять на химический состав напарника, а благодаря этому в одной клетке будет преобладать конструирование ДНК немного отличной формы. Есть такой принцип в переключателях генов, когда под действием определенных веществ они начинают генерировать нужные элементы ДНК.
Вот так в зародыше человека клетки сначала делятся, потом образуется специализация отдельных блоков, и каждая из клеток получая сигналы от соседей начинает заниматься своей кухней. Так и вырастают голова, туловище, ножки и ручки.
Действует усложненных принцип схожий с комплементарностью, который порождает всё разнообразие биосферы Земли.
Программирование
А теперь взглянем на программирование. Люди уже давно не складывают из чистых нулей и единиц свои программы, для этого они используют языки программирования высокого уровня: С++, Java, Python, PHP и многие другие. Но эти языки — это тоже результат эволюционного развития. Сначала команды в первые компьютеры действительно вводились с помощью элементарных рубильников вкл/выкл. Но постепенно техника усложнялась и начали использовать перфокарты, затем язык Ассемблер и уже после C. Понятия, которыми оперирует, программист становились всё более абстрактными появлялись: функции, классы.
Допустим, программист хорошо выучил основные элементы и написал программу, которая понравилась пользователям, и они стали её активно покупать. Однако, программист оказался ленивым и выучил он лишь небольшое количество принципов. Например, знает, как организовывать отдельные операции в функции и может быть собирать их в классы. Но так как программист очень продуктивный, то он смог описать таким образом все, чем пользуются его целевая аудитория. Такое случалось часто на заре становления программного обеспечения. Не нужно было быть слишком умным, достаточно было реализовать полностью то, что требуется. Потому что конкуренция в те времена была минимальная.
Можно сравнить эту ситуацию с древним вендским (геологическая эпоха 630 - 535 млн. лет назад) океаном. Там царили беспозвоночные и бесскелетные формы жизни, без ртов, кишечников и конечностей, даже панцирей не было, чтобы защищаться от хищников, которых похоже еще не придумала природа. Вот такое сообщество пацифистов, которые питались, просто впитывая кожей нужные им вещества. Есть парочка принципов формирования тела и поглощения веществ и этого достаточно. Пусть в результате получаются живые студни и лепешки, но большего на тот момент и требовалось.
Строение проекта нашего ленивого программиста также не отличалось особым изяществом – в основном это были длиннющие функции, делающие сразу множество вещей, никакого разделения ответственности. Просто получаем на входе данные и пытаемся, прокручивая все это через неисчислимое количество условных операторов сформировать на выходе решение. В конце концов, ведь компьютерные операции строятся все на трех операторах И, ИЛИ, НЕ, почему бы и нет, если потратить достаточное время, то так можно решить любую задачу.
Условия жизни меняются
Сто миллионов лет плавали жители Венда и бед не знали, пока не наступило глобальное оледенение. Поверхность Земли практически полностью замерзла и превратилась в снежок. Но даже в таких условиях вендские формы сохранились и продолжали жить в глубинах океана на экваторе. Однако ресурсов явно стало меньше и просто так поглощать их кожей уже не получалось, приходилось придумывать новые способы и один из вариантов – это кушать себе подобных. Хищники добро пожаловать. Вот тут появляются скелетные формы. Сначала панцири, чтобы защитить свое мягкое тело от укусов наглых соседей, а затем острые зубы чтобы прокусывать эти самые панцири.
Но скелет – это не просто дополнительная часть организма, это целый комплекс новых реакций, который должен произойти в клетках, чтобы сформировались конструкции из кальция. Вместе с этим неизбежно произошло усложнение строения. Теперь простой желеобразной структуры было мало, нужно было каким-то образом выделять отдельные части под свои задачи. А раз есть отдельные части, то они должны коммуницировать между собой и действовать согласовано. Только так можно было выживать в новом мире полным хищников и с ограниченным запасом ресурсов.
Также и нашему программисту, если он дальше хочет выживать и радовать своих пользователей новыми функциями, то ему нужно выучить дополнительные концепции и активно применять их в своей практике. Классы должны теперь не просто группироваться по функциям, но каждый из классов должен быть составным элементом и эффективно коммуницировать со своим окружением. В идеале эта коммуникация должна основываться на действиях, а не данных. Т.е. один класс должен быть подобен клетке, которая прекрасно знает что творится внутри, но будучи помещенной в среду себе подобных в результате своих действий может порождать сигналы для соседей, одними только своими действиями (публичными методами). Это очень похоже на принцип SOLID.
Что дальше?
Вполне, возможно, что развитие искусственного интеллекта привнесёт новые концепции в программирование, которые породят ещё более интересные продукты. Главное, чтобы плодами этой технической эволюции продолжали наслаждаться люди, а не какие-нибудь киборги.
Сможет ли человечество выработать панцири и зубы, которые будут соответствовать возможностям искусственного интеллекта?