О процессе разработки
- Код предназначен не только для его непосредственного выполнения, но он также является средством общения в команде и способом описать другим решение какой-либо проблемы. Написание читаемого кода — это фундаментальная часть данного процесса, а не просто “хороший тон”. Он включает в себя рефакторинг кода, выбор понятных имен переменных и добавление комментариев ко всему, что требует объяснений.
- Задумайтесь о том, что ваш pull request может сделать для пользователей и сообщества в целом, а не для вашего продвижения по карьерной лестнице. Избегайте “чрезмерного вклада” любой ценой. Не добавляйте функцию, если она не имеет никакого отношения к реальным целям вашего продукта.
- Наличие хорошего вкуса тоже относится к коду. Вкус — это процесс удовлетворения ограничений, регулируемый стремлением к простоте. Держите курс к простоте.
- Если кто-то просит вас добавить функцию — это не означает, что вы обязательно должны ее добавить. Смело отвечайте “нет”. Каждая функция имеет стоимость, которая выходит за рамки первоначальной реализации: затраты на обслуживание, стоимость документации и ваши умственные затраты. Всегда спрашивайте: нам на самом деле необходимо это сделать? Зачастую, следует ответ: “Нет”.
- Помните, что на запрос пользователя о добавлении нового сценария использования не всегда стоит отвечать “да”, так как, зачастую, запрошенный сценарий не оптимален. Пользователи сосредоточены на своем конкретном сценарии использования, а вы должны быть сосредоточены на видении всего проекта в целом. Лучше займитесь улучшением существующих функций.
- Инвестируйте в непрерывную интеграцию и стремитесь к полному юнит-тестовому покрытию. Убедитесь, что вы находитесь в среде, где можете писать код четко и уверенно. Если это не так, начните с создания правильной инфраструктуры.
- Не переживайте, если не спланировали все заранее. Пробуйте все постепенно и смотрите, что из этого выходит. Если вас что-то не устраивает, как можно раньше откажитесь от этой идеи. Убедитесь, что вы создали среду, в которой это возможно сделать.
- Хорошее программное обеспечение упрощает процесс работы. Если задача выглядит сложной, это не означает, что ее решение тоже должно быть долгим и трудным. Слишком часто инженеры подбирают к непростым задачам такие же решения (Давайте использовать ML! Давайте создадим приложение! Давайте добавим блокчейн!) в ситуациях, когда доступна гораздо более простая, хотя и менее очевидная альтернатива. Прежде чем начать писать код, убедитесь, что решение вашей задачи упрощено до предела возможного. Исходите из своих “изначальных принципов”.
- Избегайте непонятных правил. Правила, которые вы разрабатываете, всегда должны быть ясными и доступными для других. Всякий раз, когда вы продумываете рабочий процесс (workflow), вы должны попытаться формализовать его в документированный процесс, чтобы другие участники команды смогли извлечь из него выгоду. Более того, вы должны стремиться автоматизировать ваши рабочие процессы с помощью ПО (например, проверку корректности).
- Ваш выбор должен влиять на весь процесс проектирования, а не только на доход и развитие. Какое влияние оказывает ваше программное обеспечение на пользователей и на мир? Есть ли нежелательные побочные эффекты, которые перевешивают пользу? Что вы можете сделать, чтобы решить их, сохранив при этом всю пользу программного обеспечения?
О проектировании API
- У вашего API есть пользователи, следовательно, у API есть пользовательский опыт (UX). При принятии какого бы то ни было решения — всегда помните о пользователях. Думайте о чувствах каждого пользователя, будь то новичок или опытный разработчик.
- Старайтесь свести к минимуму умственную нагрузку на пользователей, во время использования API. Автоматизируйте то, что можно автоматизировать, снизьте количество действий и выборов, необходимых от пользователя. Не добавляйте параметры, которые не имеют значения, разрабатывайте простые и последовательные процессы работы, которые отражают простые и последовательные ментальные модели.
- Простые вещи должны быть простыми, сложные вещи должны быть возможными для выполнения. Не увеличивайте, даже минимально, умственную нагрузку сценариев общего использования, ради нишевых сценариев использования.
- Если умственная нагрузка рабочего процесса достаточно низкая, у пользователя должна быть возможность делать все по памяти (не используя документацию или учебник) после того, как он сделал это один или два раза.
- Стремитесь к тому, чтобы ваш API соответствовал ментальным моделям экспертов доменов и практических специалистов. Если у кого-то есть опыт работы с доменами, но нет опыта работы с вашим API — у него должна быть возможность интуитивно понимать ваш API, используя минимальное количество документации, в основном, просто взглянув на несколько примеров кода, доступные объекты и их сигнатуры.
- Значение аргумента должно быть понятным без какого-либо контекста, относительно базовой реализации. Аргументы, которые указываются пользователями, должны относиться к ментальным моделям, которые пользователи относят к определенной проблеме, а не к деталям реализации в вашем коде. API — это всегда о проблемах, которые решает код, а не о том, как программное обеспечение работает на заднем плане.
- Наиболее мощные ментальные модели обладают модульностью и иерархичностью. Точно так же хороший API обладает модульностью и иерархичностью: простой в обращении, однако выразительный. Существует баланс между сложными сигнатурами на меньшем количестве объектов и наличием большего количества объектов с более простыми сигнатурами. Хороший API имеет разумное количество объектов с достаточно простыми сигнатурами.
- Ваш API неизбежно отражает ваши варианты реализации, в частности, ваш выбор структур данных. Чтобы получить интуитивно понятный API, вам необходимо выбрать структуры данных, которые, естественным образом, подходят для домена — это соответствует ментальным моделям экспертов в области доменов.
- Умышленно проектируйте сквозные рабочие процессы, а не набор атомарных функций. Многие разработчики, проектируя API, задаются вопросом: “Какие возможности нам нужно добавить?”. Вместо этого лучше спросить: “Каков сценарий использования для этого инструмента?”. Какова оптимальная последовательность действий пользователя для каждого сценария использования? Какой самый простой API может поддерживать этот рабочий процесс? Атомарные функции в вашем API должны отвечать на явную потребность, возникающую в высокоуровневом рабочем процессе. Функции по типу “вдруг кому-то это может понадобиться” не следует добавлять. Они не нужны!
- Сообщения об ошибках, и, как правило, любая обратная связь, предоставляемая пользователю в процессе взаимодействия с вашим API — это часть API. Интерактивность и обратная связь являются неотъемлемой частью пользовательского опыта. Нарочно создавайте сообщения об ошибках в API.
- Код — это средство общения, поэтому так важно присваивать имена, например, проекту или переменным. Имена отражают ваше отношение к проблеме. Избегайте распространенных названий (x, variable, parameter), избегайте ЧрезмерноДлинныхИСпецифичныхНазваний, избегайте терминов, которые могут создать ненужные разногласия (master, slave) и убедитесь, что вы последовательны в выборе имен. Последовательность в выборе имен означает как внутреннюю последовательность (не называйте “dim”, то что называется “axis” в других местах), так и последовательность с установленными соглашениями для проблемного домена. Прежде чем выбрать имя, обязательно проверьте существующие имена, используемые экспертами в области доменов (или другими API).
- Документация занимает центральное место в UX вашего API. Она не является дополнением к API, как многие ошибочно полагают. Инвестируйте в высококачественную документацию и вы получите более высокую прибыль, чем при инвестировании в другие функции.
- Показывайте, а не рассказывайте: ваша документация не должна говорить о том, как работает программное обеспечение, она должна показывать, как его использовать. Продемонстрируйте примеры кода для сквозных рабочих процессов; примеры кода для каждого распространенного сценария использования и ключевых функций вашего API.
О карьере в сфере программной инженерии
- Карьерный рост — это не то, каким количеством людей вы управляете, а то какое влияние вы оказываете: разница между миром, в котором есть ваши плоды работы и миром, где их нет.
- Разработка программного обеспечения — это командная работа; речь идет как о взаимоотношениях, так и о технических навыках. Будьте хорошим товарищем. Когда вы целенаправленно идете к своей цели, не забывайте о других людях.
- Технологии никогда не бывают нейтральными. Если ваша работа оказывает какое-то влияние на мир, то это влияние имеет нравственный характер. Казалось бы, безобидный технический выбор, который мы делаем в программных продуктах, моделирует условия доступа к технологии; стимулы ее использования; кто выиграет, а кто пострадает от этого. Технический выбор — это также этический выбор. Поэтому всегда будьте целенаправленны и откровенны, относительно ценностей, которые вы хотите поддерживать и продвигать. Воплощайте свои ценности в своих творениях.
- Самоуправление — свобода воли в работе и складывающихся обстоятельствах — это ключ к удовлетворенности жизнью. Убедитесь, что вы предоставляете достаточно самостоятельности окружающим вас людям и убедитесь, что выбранная вами карьера приведет к большей свободе воли для вас.
- Создайте для мира то, что нужно ему, а не то, что хочется вам. Слишком часто инженеры живут в своем выдуманном мире, сосредоточившись на продуктах, удовлетворяющие их конкретные потребности. Ищите возможность расширить свой жизненный опыт, который позволит вам лучше понять, что нужно миру.
- Делая выбор с долгосрочными последствиями, ставьте свои ценности выше краткосрочных личных интересов, а также отбрасывайте ненужные эмоции, например, жадность или страх. Позвольте вашим ценностям, а не эмоциям вести вас.
- Когда вы вступаете в конфликт, сделайте паузу и напомните друг другу об общих ценностях и целях. Наверняка вы находитесь на одной стороне баррикад.
- Продуктивность сводится к высокой скорости принятия решений и склонности к действию. Это требует: a) хорошей интуиции, которая основывается на жизненном опыте, чтобы принимать правильные решения при минимуме информации; б) четкое понимание того, когда нужно действовать более осторожно и ждать дополнительной информации, поскольку цена неправильного решения будет выше, чем стоимость отсрочки. Оптимальный компромисс между скоростью и качеством принятия решений может сильно отличаться при различных условиях.
- Быстрое принятие решений увеличивает количество решений, которые вы совершаете в течение всей своей карьеры. В итоге это приводит к повышению уровня вашей интуиции при принятии решений. Опыт является ключом к высокой производительности, а высокая производительность дает вам больше опыта: весьма эффективный цикл.
- В ситуациях, когда вы осознаете, что интуиция не помогает, придерживайтесь абстрактных принципов. Создайте список проверенных принципов и пополняйте его на протяжении всей карьеры. Принципы — это официально оформленная интуиция, которая затрагивает более широкий круг ситуаций и требует от вас намного меньше опыта.
Перевод статьи François Chollet: Notes to Myself on Software Engineering