Именованные параметры - повышаем читабельность кода

Наверное каждый разработчик достаточно часто сталкивается с кодом вида:

List<Products> productList = GetProductsById(id, 8, 15);
При беглом прочтении часто возникает вопрос: а что обозначают числа 8 и 15?

И если в случае с числовыми или строковыми значениями иногда можно догадаться о их назначении, то булевские зачастую ставят в тупик:

IEmployeeDataSource dataSource = CreateEmployeeDataSource(true);

Или вот такой пример:

this.PostPage (pageId, false);

Давайте рассмотрим варианты избавления кода от подобных "магических" значений. При этом сравним два стандартных способа с одним, специфичным для C# 4.

Применение констант

В этом случае в теле метода или класса добавляется переменная-константа, имя которой поясняет назначение её значение. Например:

const int startAtPage8 = 8;
const int show15ItemsPerPage = 15;
// ...
List<Products> productList = GetProductsById(id, startAtPage8, show15ItemsPerPage);


const bool useLocalStorage = false;
// ...
IEmployeeDataSource dataSource = CreateEmployeeDataSource(useLocalStorage);
    
const bool postPrintVersion = true;
// ...
this.PostPage (pageId, postPrintVersion);

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

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

Определение перечисления

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

enum StorageType { Local = false, Online = true }
// ...
IEmployeeDataSource dataSource = CreateEmployeeDataSource(StorageType.Local);
                
            
enum PageVersion { Web = false, Print = true }
// ...
this.PostPage(pageId, PageVersion.Web);

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

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

Еще один отрицательный момент заключается в необходимости изменения типа параметра или  приведения значения перечисления к исходному типу.

Использование именованных параметров

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

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

List<Products> productList = GetProductsById(id, startAtPage: 8, itemsPerPage: 15);

IEmployeeDataSource dataSource = CreateEmployeeDataSource(useOnlineStorage: false);

this.PostPage(pageId, isPrintVersion: false);

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

Комментарии (15) -

Спасибо! Не знал Smile

Анонимус 02.02.2011 0:14:11

А под VB.NET есть что-то похожее?

Спасибо, Кэп!

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

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

to guest

про enum
да да да))) здорово! делаем на пример платную библиотеку.
и что отвечаем пользователям на их "глупые", по вашему,
вопросы, по поводу обрашения к вашим методам?
мышку не так наводили? попробуйте еще раз?
очень выгодная позиция для вашего кошелька.

про именованные параметры
когда в проекте более 100 классов, и масса методов,
возвращаясь к какому либо разделу кода через пару месяцев.
не очень легко бывает сразу правильно сориентироваться.
не нужно ля ля. перечитывать каждый раз код не "професссионально".
если к вам применим этот термин.

Василий 02.02.2011 13:01:05

Всегда нравился ваш стиль. Но вот и у вас появилось это "читабельность". Почему не читаемость. Откуда такая традиция? Ухо режет.

Есть стандартное описание сигнатуры методов в коде программы

        /// <summary>
        /// Описание метода...
        /// </summary>
        /// <param name="Name">Описание параметра...</param>
        /// <returns>Описание возвращаемого значения...</returns>
        public int GetID(String Name)
        {
            ...
        }

guest
Даже когда пишем "для себя", то зачем лишние телодвижения? Про коммерческий код уже сказали. Да и при работе в команде то же самое.

Разумеется у всех свой вкус (про стандарты кодирования в фирмах не говорю – там как скажут, так и пишем). Но разбирать чужой код, который легко читается и правильно документирован куда легче и приятнее.

Alexandr
Есть, но одно другого не отменяет. Кроме того, есть даже вспомогательные средства для упрощения создания таких комментариев. Про GhostDoc я уже упоминал в этом блоге. Но все равно необходимы лишние движения мышкой. И дело не в лени. Это как отделка салона в дорогих авто – на вождение явно не влияет, но ехать то приятнее.

Василий
Наверное сказывается что большую часть читаю на английском. Хотя стараюсь все же не увлекаться подобной терминологией. Хотя по поводу данного термина я все же сомневался, но и "читаемость" тоже звучит как-то не очень.

Бред. Тогда давайте var не использовать. А то получается при беглом прочтении "Боже, что мне делать, я не знаю что возвращает эта функция..."
Ну а тут уже и до венгерской нотации недалеко. "Боже, что мне делать, я не знаю какого типа эта переменная..."
И последнее. Такие случаи встречаются довольно редко.

Dog ну лично я предпочитаю var только тогда, когда возвращаемый тип очевиден. Например, очень удобно c new при создании экземпляров generic классов, да еще с несколькими типами в качестве параметров. Кстати, это как раз улучшает код, т.к. часто позволяет сократить длину строки до удобочитаемой. А раскидывать везде var - не по мне. Разумеется, говорю только за себя и не навязываю такой стиль.

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

Под Visual Basic давно есть, собственно из него и пришло.

Dim productList As List(Of Products) = GetProductsById(id, startAtPage := 8, itemsPerPage := 15)

Andrey добавил в друзья на facebook. у нас оказывается есть общие знакомые. получается из одной тусовки).

@ guest:

Не всегда есть возможность использовать Intellisense (например, используется бесплатная IDE).

Pingbacks and trackbacks (1)+

Добавить комментарий