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

Возьмем слова «шарик» и «штапель». Как добраться до слова «штапель», начав с «шар»? Какая связь?

Ваша первая попытка может быть примерно такой: мяч -> баскетбол -> НБА -> Лейкерс -> Стейплз Центр -> Стейпл. Затем вы можете удалить «баскетбол», потому что для человека связь между «мячом» и «баскетболом» очень очевидна, делает ее даже излишней. Опять же, нужно ли нам явно связывать «мяч» с «нба», прежде чем мы сможем перейти к «Лейкерс»? На самом деле «Лейкерс» выходит за рамки только баскетбольного сообщества и представляет собой концепцию, широко известную в той мере, в какой не нужны дополнительные ссылки для ее объяснения и предоставления контекста. На данный момент мы дошли до: мяч -> Лейкерс -> Стэйплз Центр -> Стейпл. На данный момент мы можем договориться с этой цепочкой. Если вы фанат баскетбола, вы, вероятно, чувствуете себя уверенно, даже убрав из списка слово «главный центр скобок», потому что связь между «лейкерс» и «основным продуктом» очевидна.

Игра была развлечением для нас в детстве, когда нам не на что было отвлечься. Становится интересно, когда вы добавляете правило, согласно которому вы должны угадать точный путь, который имел в виду другой человек. Помимо отвлечения от скуки, это упражнение также служило тренировкой ума для распознавания закономерностей и связей между, казалось бы, несвязанными понятиями.

Вот я, много лет спустя, думаю об игре, в которую я играл со своим братом более двух десятков лет назад. Игра, о которой я не думал уже столько лет. Причина, по которой это пришло мне в голову, в том, что я позволил своему разуму задаться вопросом, а затем, в конце, спросил себя: «Как я начал думать об X?». Удивительно то, что я начал играть в ту же игру с самим собой, чтобы проследить, с какой исходной мысли я начал. Мой разум начал перескакивать с одной идеи на другую, устанавливая связи между ними, и все это в считанные секунды. Вот когда это щелкнуло.

Мой мозг все эти годы играл в одну и ту же игру. Единственная разница в том, что я больше не делал это для развлечения, это было то, за что мне платили. Распознавание шаблонов и поиск пути от начальной точки X до конечной точки Y — вот в чем заключается моя работа как разработчика. Единственная разница в том, что мне больше не нужно было искать кратчайший путь, соединяющий X и Y, фактически я должен был выполнить противоположное упражнение. Программирование фактически заполняет пробелы между каждой ссылкой. Давайте рассмотрим пример…

Представьте, что вас попросили создать клон Dropbox, инструменты, которые у вас есть, — это примитивные типы, которые предоставляет вам любой язык программирования. Так как же перейти с Integers/Strings/Arrays/etc на Dropbox? Это самое интересное. Ради этого примера мы проигнорируем часть загрузки файла с компьютера в облако, просто будем считать, что файлы где-то доступны и у вас есть соответствующий путь. С чего начать?

Обычно я начинаю с того, что задаю несколько вопросов по сбору информации, например: Что такое Dropbox? Простой ответ (упрощенный, само собой разумеющийся) заключается в том, что Dropbox — это хранилище файлов, организованное в виде структуры каталогов, с некоторыми разрешениями, разбросанными поверх него. Начиная с этого простого определения, мы можем выделить пару ключевых понятий, в основном то, что у нас есть «репозиторий файлов». Мы можем использовать это, чтобы провести некоторые связи между нашей концептуальной моделью и кодом. Мне нравится использовать некоторую замену слов, чтобы сделать связи более ясными, поэтому, заменив «репозиторий файлов» на «список файлов», мы получаем помощь от использования общей терминологии, которая может связать концепцию с реализацией. Список — это нетехнический термин, который все понимают, но использование этого конкретного слова вызовет связь в сознании разработчика, потому что концепция списков — одна из самых основных в программировании. В нашем случае мы будем использовать простую конструкцию списка, которая называется Array. Объединив то, что у нас есть, мы знаем, что файлы представляют собой Array путей, а это Strings. Так что, может быть, что-то вроде my_dropbox_clone = [ 'image1.png', 'image2.png', ...]. Просто, не очень полезно, конечно, но это на шаг ближе. Теперь нам нужно найти следующее звено и связать его.

В настоящее время все наши файлы собраны в одном списке. Нам нужен способ обозначить разные репозитории и файлы, принадлежащие каждому из них. Итак, если мы начали с одного массива, то наличие нескольких каталогов просто означает, что у нас есть массив массивов:

my_dropbox_clone: [
  'image1.png',
  [ 'image2.png', [ 'file1.pdf' ] ]
]

Итак, у нас есть корневой каталог с одним изображением и одним подкаталогом. В этом подкаталоге у нас есть еще одно изображение и еще один подкаталог. И так далее. Но чего-то все еще не хватает. Каталоги имеют имена, и это имя является частью пути к файлу. Итак, хотя каталог — это список файлов, это только часть полной картины, каталог — это имя + список ( + некоторые другие метаданные). Это означает, что нам нужна другая структура данных, которая может инкапсулировать как список (Array), так и имя. На ум приходит Hash:

my_dropbox_clone = {
  name: '',
  content: [
    'image1.png',
    {
      name: 'vacation',
      content: [
        'image2.png',
        {
          name: 'receipts',
          content: [
            'file1.pdf'
          ]
        }
      ]
    }
  ]
}

Если бы вас попросили перечислить каждый каталог и его содержимое, учитывая приведенную выше структуру, смогли бы вы это сделать? Я так считаю. У вас есть каталог, который представлен Hash, чтобы отобразить каталог, вам просто нужно отобразить его имя, а затем список всего в его содержимом. Содержимым каталога могут быть другие каталоги, которые следуют тому же правилу, или файлы, которые представлены String, и вы просто распечатаете это.

Сделав еще один шаг вперед, вы можете начать визуализировать, как можно определить путь к каталогу (соединив имена всех его родителей с / между ними), как добавить/удалить новые файлы или каталоги (добавить/удалить элементы из атрибута content каталога).

Конечно, на самом деле мы не создали настоящего клона Dropbox, но вы же не думали, что мы действительно добьемся этого, просто используя примитивные типы, не так ли? 😉
Однако мы начали с двух концепций (Dropbox и примитивные типы), а затем восполнили пробелы, определив шаблон для соединения, а затем добавив ссылки в нашу цепочку, чтобы приблизиться к полному решению.

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