Собрал в статье рекомендации, как и где писать новые функции, а также предпосылки к декомпозиции существующих. Всё это имеет смысл, когда хочется получить на выходе красивый и лаконичный код, который приятно анализировать и легко сопровождать.
Можно выделить ситуации, говорящие о том, что стоит вынести часть кода в отдельную функцию.
Код выглядит сложным и неочевидным. Простота – одна из самых главных характеристик хорошего кода. Простой код легко понять – он последователен и прямолинеен, не содержит сложных неочевидных вызовов и запутанной обработки ошибок. Также он не берёт на себя лишней ответственности, делая только то что от него ждут. Выделяя и разбивая сложные конструкции в отдельные функции, можно значительно повысить читаемость кода.
Функциональность сложно модифицировать или расширять. Обдумывая потенциальные изменения функциональности модуля или сущности (в том числе при наследовании и перекрытии), необходимо проектировать её так, чтобы адаптация, при её необходимости, проходила как можно легче и имела как можно меньше влияния на другие элементы разработки. Куда проще перекрыть один метод, чем переписывать всю цепочку вызываемых функций, попутно усложняя сопровождаемость всего механизма в долгосрочной перспективе.
Код занимает более 1-2 экранов монитора. Удобнее всего в один момент времени видеть весь необходимый код перед глазами. Перевести взгляд от одной части статичного изображения к другой гораздо проще, чем прокручивать страницу, теряя из-за этого ранее анализируемую строчку кода. При разрастании функции на несколько экранов монитора, анализ и сопровождение становится более трудоёмким в следствие усложнения читаемости. Рекомендуется избегать функций больше 2 экранов (примерно 90 строк). Большинство функций, в идеале, должно быть меньше 1 экрана (примерно 45 строк).
При выборе места размещения функции рекомендуется задавать себе вопрос: откуда вызывать эту функцию будет логичнее всего? Определите контекст, в котором функция смотрелась бы наиболее правильно с точки зрения объектной модели и где разработчик стал бы искать её в первую очередь.
Не рекомендуется размещать функции в решениях. Лучше размещать функции в модулях или типах сущностей. При разработке больших и сложных решений как правило выделяют модуль, который содержит всю общую логику решения, включая функции, также общие для всего решения.
Функции модуля создаются, когда предполагается, что одна и та же логика будет выполняться в нескольких типах сущностей и отчетах модуля, а также в других модулях. При этом такие функции не имеют жёсткой привязки к конкретному типу сущности, а выполняют общую логику, характерную и уникальную для этого модуля.
Примеры: конвертация документов в PDF; функции интеграции; действия обложки модуля; общие вычисляемые выражения.
Функции типов сущностей создаются, когда предполагается, что одна и та же логика будет выполняться в нескольких действиях, событиях или других функциях этого типа. Также такие функции могут вызываться в других модулях или типах сущностей. Эти функции имеют логическую привязку к конкретному типу. Это значит, что функции характерны и уникальны для этого типа сущности.
Примеры: функции изменения состояния сущности; расчёт признака на основе свойств; получение конкретной сущности, созданной на инициализации.
Функции инициализации создаются исключительно для инициализации модуля, в котором они определены.
Примеры: создание ролей; создание сущностей; выдача прав для ролей.
Информация о видах кода есть в справке.
Выполняются в клиентском приложении.
Обратите внимание, что при веб-доступе физически выполняются на веб-сервере.
Для клиентского кода существуют ограничения, связанные с трехзвенной архитектурой и оптимизацией работы системы через интернет.
Код используется для:
Примеры: показ диалога; валидация с выводом ошибки.
Выполняются на сервере.
Так как серверный код выполняется на сервере, в нем не должно быть логики, которая связана с пользовательским интерфейсом (GUI). Это означает, что в серверном коде запрещено показывать окна, выводить диалоги.
Код используется для:
Примеры: удаление документа; выполнение запроса в БД; функция интеграции.
Выполняются в любом коде.
На разделяемый код накладываются ограничения одновременно и серверного, и клиентского кода. Таким образом, в разделяемом коде нельзя работать с пользовательским интерфейсом, напрямую создавать, удалять и получать сущности, а также всё то, что было описано выше.
Используется для:
Примеры: валидация сущности; заполнение свойств по алгоритму; установка обязательности свойств.
Вот основные рекомендации.
В имени используйте нотацию PascalCasing, для этого пишите первую букву каждого слова в верхнем регистре.
Имена должны передавать намерения программиста. В разных ситуациях от имени может требоваться отвечать на целый ряд вопросов (это зависит от контекста и от наличия перегрузок этой функции), но обобщая можно выделить три главных: почему она существует, что она делает и как используется.
Имена функций следует задавать как можно короче, иногда пренебрегая правилами построения предложений в английском языке, используя минимально необходимый набор слов. При этом они должны быть осмысленными и говорящими, так как в дальнейшем это упростит читаемость кода и понимание другими разработчиками. Если возникает вопрос в выборе между содержательностью и краткостью, рекомендуется делать упор на большую содержательность.
Сокращения не должны влиять на понятность имени. Не используйте аббревиатуры или неполные слова, если только они не являются общепринятыми.
Обращайте внимание на то, как названы другие функции в текущей сущности/модуле. Старайтесь придерживаться стиля именования уже имеющегося кода. Различия в стилях имён функций одной области кода бросаются в глаза куда сильнее чем общее несовершенство стиля. В данном случае единообразие будет более ценно (в противном случае можете заняться рефакторингом всех функций "вокруг", если на то позволяют ресурсы).
Документируйте функции в XML-формате. Чтобы быстро сформировать описание по формату, в среде разработки над определением функции введите ///. В результате автоматически вставится структура комментария.
Обязательно заполняйте описание функции (<summary>), параметров (<param>), выходного значения (<returns>), а также, при необходимости, примечание (<remarks>). В долгосрочной перспективе эти действия принесут немало пользы другим разработчикам (и вам в том числе).
Также информацию о правилах именования и документирования можно найти в справке.
Внутри кода рекомендуется использовать регионы (#region) для объединения логически связанных функций или обработчиков.
Ниже будут представлены самые удачные примеры использования регионов.
При инициализации происходит множество разнообразных действий, таких как:
Для создания понятной структуры функций инициализации рекомендуется группировать их в логические регионы. Рекомендуется использовать в качестве шаблона структуру инициализации модуля Sungero.Docflow.
Любой элемент системы может содержать в себе огромное количество логики, а значит и функций. Чтобы было проще ориентироваться в коде, рекомендуется объединять связанные по назначению функции в регионы.
Напомню, что большие функции следует разбивать на более простые. Но если всё таки нет такой возможности "здесь и сейчас", а минимальный порядок и читаемость обеспечить важно - можно воспользоваться тем же регионом для разделения разнородных вычислений внутри функции. Это позволит сворачивать массивные блоки кода, которые в текущий момент не требуют внимания разработчика, а только мешают процессу анализа или разработки. Но будьте осторожны - в свёрнутом регионе могут "прятаться" важные вычисления, которые влияют на код ниже.
При разработке новых типов задач может быть проблематично ориентироваться в коде их блоков. Для упрощения работы с кодом рекомендуется группировать события в регионы соответствующих блоков.
Если код модуля или сущности содержит множество функций, связанных с разными механизмами, то можно воспользоваться группировкой кода в разные файлы.
Этот способ позволит облегчить и ускорить навигацию по следующим причинам:
Подробную информацию о группировке, а также пример можно найти в справке.
Авторизуйтесь, чтобы написать комментарий