«Учитесь ломать вещи». Белорусский iOS-разработчик — про анализ и синтез в программировании
О роли анализа и синтеза в программировании рассуждает в своей колонке Игорь Шавловский, Lead iOS-разработчик в neoviso.
Спросите любого человека, что означает термин «анализ» — вероятно, он ответит неправильно. Попробуйте сперва дать определение самостоятельно, а потом проверить его, например, в Википедии.
Анализ — это выделение частей какого-то объекта. Поэтому, когда кто-то говорит, что анализирует, он имеет в виду «я ищу кусок в целом» либо «я думаю». Причём, второй вариант — неправильное использование термина.
Слово «синтез» в бытовой речи используется намного реже. Под ним понимают объединение частей в целое. Например, термоядерный синтез — это не какой-то абстрактный процесс, происходящий в реакторах, а конкретное объединение ядер лёгких элементов в более тяжёлые, создание сложных атомов. Упрощённо можно сказать, что анализ — это поиск простого в сложном, а синтез — создание сложного из простых частей.
Где в этом лингвистическом экскурсе программирование?
А программирование — это и есть повторяющаяся цепочка анализа и синтеза.
В своей работе я в том числе провожу собеседования с соискателями. Независимо от образования, опыта и заявленных навыков, первые несколько технических вопросов всегда касаются аналитических способностей кандидата. Это необходимо для того, чтобы найти такую задачу, на которую у него не будет готового ответа. А значит, придётся решать проблему «здесь и сейчас».
Многие выпускники вузов или курсов начинают искать в голове готовые шаблоны, которые можно применить для решения задачи. Ели это сортировка — обязательно произносят названия методов, останавливаются на каком-то одном, а уже потом вспоминают, сколько там было циклов, где надо перебирать до count, а где до count - 1. Если задача на работу со строками — будут вспоминать функции конкретного языка, которые и выдаются в качестве ответа. И все эти ответы обычно неверные, поскольку они не являются результатом анализа поставленной задачи. А ведь аналитическое мышление — важнейший навык программиста, без которого быстрое и качественное решение проблем невозможно.
Когда я нахожу для кандидата критическую задачу, хочу, чтобы он начал её анализировать, разделять на простые операции, а в случае тупика сказал, какую именно часть он не может упростить. Единственными вопросами, возникающими на этапе анализа, должны быть уточнения поставленной задачи. И любой, у кого не возникнет проблемы в построении алгоритма, имеет все шансы получить работу.
Навыки синтеза, заключающиеся в написании кода по готовому алгоритму, развить намного проще. Для этого фактически нужны лишь знания общих требований к оформлению кода и синтаксиса языка программирования. Это тот фиксированный набор знаний, который надо получить по каждому языку программирования один раз в жизни.
Программист — не профессия, а образ мышления
Всё сказанное подводит к очевидному для меня факту: программист = алгоритмизатор. Это образ мышления и конкретный подход к решению задач.
С чего начинается программа? С технического задания. В мобильных приложениях — это набор экранов, в web-приложениях — набор страниц и шаблонов, в системных/прикладных модулях — список нужных методов с описанием входных данных и ожидаемого результата. Техническое задание обычно содержит в себе лишь описание внешнего вида приложения, функции элементов интерфейса, требования к скорости работы и используемым ресурсам. И служит оно отправной точной для анализа. Изначально программист выбирает шаблон построения приложения (к примеру, MVC, MVP, MVVM), дальше — экран за экраном, требование за требованием, предложение за предложением задание раскладывается на полочки выбранного шаблона. Для каждого элемента интерфейса необходимо понять, откуда он получит данные и куда отправит по нажатию кнопки, как будут загружаться и храниться данные, как обрабатываться.
Таким образом, один объект — техническое задание — разбивается на тысячи мелких действий, структур данных, запросов, библиотек, шаблонов. Описание программы превращается в алгоритм — список операций, которые должна выполнить система, чтобы получить необходимый результат.
Алгоритм представляет собой набор инструкций, которые выполняются последовательно. Часть может повторяться (цикл), пропускаться (условные операторы), инкапсулироваться в отдельные сущности (функции, методы). В многоядерных системах множество алгоритмов выполняется параллельно, асинхронно взаимодействует друг с другом и с операционной системой. Правильно построенные алгоритмы — это 90% качества готового продукта.
Завершив раскладывать техническое задание на компоненты, программист приступает к синтезу — выбирает любую часть алгоритма и начинает писать её на определённом языке программирования. Так абстрактный набор инструкций превращается в куски программного кода.
Всё просто: работа программиста заключается в повторении циклов построения алгоритма и его реализации.
Как искать баги?
Второй большой частью работы программиста всегда являлся дебаг, оптимизация и поиск ошибок. Именно эти задачи всегда были проблемами для тех, кто учил программирование по шаблонам и забывал о развитии навыков алгоритмизации. Когда программа кажется волшебной коробкой, которая временами зажигает нужные пиксели, сложно понять, за что взяться для поиска причин возникших проблем. Другое дело, если программист во всём видит набор действий, структур, потоков. Тогда даже самые неожиданные и непонятные баги можно пофиксить очень быстро.
Если вы получили задание починить баг в чужом коде, надо чётко понимать, что есть алгоритм, который работает с конкретными данными и даёт определённые результаты.
1. Подступая к багу, локализуйте его. Определите, в какой момент времени или после какого действия он случается, найдите код, ответственный за это действие, убедитесь в том, вошли ли в этот код правильные данные, корректно ли эти данные обработались, верно ли отобразились.
2. Когда будет найден ответ, в какой части алгоритма содержится проблема, перемещайтесь к её источнику:
- если неправильными были входные данные, ищите алгоритм, который их готовит;
- если данные были правильные, но в результате обработки получен некорректный результат, ищите ошибку в текущем алгоритме;
- если ответ корректен — проблема заключается в коде отображения результата.
Сложно найти ошибку, если смотреть на приложение как на единое целое. Но, когда перебираешь его модуль за модулем, класс за классом, метод за методом, строчка за строчкой — всё сразу становится на свои места.
Сегодня профессия программиста уже стала одной из самых востребованных в мире. Появляются новые компании, растут существующие, новые вакансии можно находить каждый день. Многие мои знакомые озабочены меняющимся рынком технологий, трендами, популярными подходами к разработке. Они стремятся успевать за ними, изучать современные фреймворки. Всё это делается для того, чтобы оставаться востребованными для потенциальных работодателей.
Действительно, многие компании ищут себе программистов с опытом работы на конкретном стеке технологий. На позиции ниже сеньора достаточно просто знать суть технологии, чтобы получить рабочее место. Но это знание не гарантирует решение прикладных задач, так как оно никак не связано с умением составлять алгоритмы, которые будут реализовывать эти задачи.
С моей точки зрения, гораздо важнее нанять человека с хорошими аналитическими навыками, алгоритмизатора, который не растеряется в незнакомой ситуации, будет в состоянии видеть свой код внутри работающего приложения, понимать его слабые места. А технологии можно освоить в относительно сжатые сроки без особых трудностей. Ведь лучший способ сделать это — разобрать на части готовый работающий код и понять, как алгоритмы реализуются на данном фреймворке.
Так что ищите для себя интересные проекты и реализуйте их, беритесь за сложные задачи и старайтесь разделять их на множество простых. В погоне за новыми технологиями не забывайте о фундаменте – аналитическом мышлении, которое надо постоянно развивать.
Колонка подготовлена при участии Яны Меллер