Порядок параметров в методе (и вообще про порядок членов)
От: Shmj Ниоткуда  
Дата: 17.04.16 20:59
Оценка:
Вот, задумался.

В каком порядке лучше писать параметры в методе? Видимо лучше по смыслу, чем по алфавиту. Но какой лучше принцип применить? По очереди появления в теле метода? По важности (менее важные, опциональные, уже после).

Я старался по важности. Но когда параметров много, сложно отследить их важность.

Или вообще без всякого порядка, просто хаотично?

Кто что думает?

Добавлю. И даже более широкий вопрос. Вот, порядок полей и свойств в классе, порядок методов. Должен ли он быть? Или просто хаотично?

Update. Добавлю пример:

class Book
{
   public string Author {get; set;}
   public DateTime PublishDateTime  {get; set;}
   public string Name {get; set;}
   public long Id {get;set;}
   public DateTime PurchaseDateTime {get; set;}
   public int AvailableCount {get; set;}
   public string Description {get; set}
}


Не кажется ли вам, что сначала нужно расположить Id, книги, а не в середине. Потом желательно Name. А может Author? Вот как тут понять? А потом что первым AvailableCount или PublishDateTime?
Отредактировано 18.04.2016 1:12 Shmj . Предыдущая версия . Еще …
Отредактировано 17.04.2016 21:08 Shmj . Предыдущая версия .
Re: Порядок параметров в методе (и вообще про порядок членов
От: Sinix  
Дата: 17.04.16 21:40
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Я старался по важности. Но когда параметров много, сложно отследить их важность.


Ну так не делайте много параметров Если даже вам тяжело — остальным-то как?

Кэп: код пишется, чтобы его читали. Параметры обычно располагаются в порядке "с чем работаем, как обрабатываем, что возвращаем", параметры добавляются в том порядке, в котором они появляются в перегрузках, ref, out, params — в конце.
Этот порядок устоялся уже лет 15 как, единственное, что появилось совсем недавно — красивая схема по использованию optional args в public api.

S>Добавлю. И даже более широкий вопрос. Вот, порядок полей и свойств в классе, порядок методов. Должен ли он быть? Или просто хаотично?

Про порядок членов в классе — тынц
Автор: Sinix
Дата: 21.05.15
Отредактировано 17.04.2016 21:43 Sinix . Предыдущая версия .
Re: Порядок параметров в методе (и вообще про порядок членов)
От: #John Европа https://github.com/ichensky
Дата: 17.04.16 21:54
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Вот, задумался.


S>В каком порядке лучше писать параметры в методе?

S>Я старался по важности. Но когда параметров много, сложно отследить их важность.
1. Не изменяемые, изменяемые, опциональные.
2. Если параметров больше 5ти, то скорее всего метод надо разбить на несколько или поля объеденить в одну модель.
3. В контрукторе желательно вообще не больше 3х.

S>Вот, порядок полей и свойств в классе, порядок методов. Должен ли он быть? Или просто хаотично?

-- как принято в команде. мне нрав.так:
1. определения вложенных типов данных(енумов, структур, классов)
2. приватные поля
3. ивенты
4. свойства
5. конструкторы
6. методы
7. приватные методы

если приватный и публичный методы оч. близки по смыслу то можно их объеденить в один #region
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[2]: Порядок параметров в методе (и вообще про порядок членов
От: Shmj Ниоткуда  
Дата: 18.04.16 01:04
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Ну так не делайте много параметров Если даже вам тяжело — остальным-то как?


Количество определяется не вашим желанием а бизнес-требованиями.

S>>Добавлю. И даже более широкий вопрос. Вот, порядок полей и свойств в классе, порядок методов. Должен ли он быть? Или просто хаотично?

S>Про порядок членов в классе — тынц
Автор: Sinix
Дата: 21.05.15


Да я не об этом. Вот просто все свойства, допустим их 15 штук. В каком порядке их расположить друг относительно друга? Просто хаотично? Или по алфавиту? Или как?
Re[2]: Порядок параметров в методе (и вообще про порядок чле
От: Shmj Ниоткуда  
Дата: 18.04.16 01:10
Оценка:
Здравствуйте, #John, Вы писали:

J>1. Не изменяемые, изменяемые, опциональные.

J>2. Если параметров больше 5ти, то скорее всего метод надо разбить на несколько или поля объеденить в одну модель.
J>3. В контрукторе желательно вообще не больше 3х.

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

Давайте начнем с порядка полей, аналогичное будет и для параметров. Вот пример:

class Book
{
   public string Author {get; set;}
   public DateTime PublishDateTime  {get; set;}
   public string Name {get; set;}
   public long Id {get;set;}
   public DateTime PurchaseDateTime {get; set;}
   public int AvailableCount {get; set;}
   public string Description {get; set}
}


Не кажется ли вам, что сначала нужно расположить Id, книги, а не в середине. Потом желательно Name. А может Author? Вот как тут понять? А потом что первым AvailableCount или PublishDateTime?

Хотелось бы не думать об этом а действовать по строгому алгоритму. Ведь не всегда однозначно что должно быть первым а что вторым... Или вообще по алфавиту делать?
Отредактировано 18.04.2016 1:11 Shmj . Предыдущая версия .
Re: Порядок параметров в методе (и вообще про порядок членов)
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 18.04.16 05:05
Оценка: 23 (1)
Здравствуйте, Shmj, Вы писали:

S>Вот, задумался.


+1. Со мной тоже периодически такое происходит!

S>В каком порядке лучше писать параметры в методе? Видимо лучше по смыслу, чем по алфавиту. Но какой лучше принцип применить? По очереди появления в теле метода? По важности (менее важные, опциональные, уже после).


S>Я старался по важности. Но когда параметров много, сложно отследить их важность.


S>Кто что думает?


Как уже написал, ув. Sinix с параметрами обстоят дела довольно просто: как только возник вопрос, в каком порядке их писать, то нужно бросать все и менять код. Нет, серьезно. Если поля класса можно сгруппировать (о чем ниже), можно легко выделить в класс, то с параметрами ничего такого сделать не выйдет. Если не указывать имена аргументов, то в методе с параметрами больше 3-х понять, что означает строка в позиции 4 уже вообще невозможно.

Я обычно следую таким гайдлайнам: если параметров больше 4-х и я не могу поменять код, то обязательно при вызове подобного метода использую именованные параметры. Если же это мой код, то начинаю думать, как менять дизайн.

Тут есть несколько вариантов: 1) можно попробовать сгруппировать параметры по смыслу в отдельные сущности. 2) использовать паттерн Builder, который будет содержать методы типа `WithPublicationDate`, который будет отвечать за установку определенного поля. 3) отказываюсь от метода в пользу использования открытых свойств (валидно ТОЛЬКО для дата-объектов).

S>Добавлю. И даже более широкий вопрос. Вот, порядок полей и свойств в классе, порядок методов. Должен ли он быть? Или просто хаотично?


Это более конкретный и даже несколько простой вопрос. Но ответ на него тоже похож на предыдущий: как только возникает вопрос с порядком следования полей, то сразу же стоит задуматься над тем, а все ли нормально с дизайном. У этого правила есть пара исключений: 1) злой легаси код или 2) дата-объекты.

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

Вот исходный пример

S>
S>class Book
S>{
S>   public string Author {get; set;}
S>   public DateTime PublishDateTime  {get; set;}
S>   public string Name {get; set;}
S>   public long Id {get;set;}
S>   public DateTime PurchaseDateTime {get; set;}
S>   public int AvailableCount {get; set;}
S>   public string Description {get; set}
S>}
S>


class Book
{
    public long Id { get; set; }
    
    public string Author { get; set; }
    
    public string Name { get; set; }
    public string Description { get; set;}
    
    public DateTime PublishDateTime { get; set; }

    public DateTime PurchaseDateTime { get; set; }
    
    public int AvailableCount { get; set; }
}


Я бы ставил Id вначале, поскольку это, скорее всего, дата объект. Потом я бы поставил автора или же Name, поскольку кажется, что это ключевые аспекты нужные при анализе этого домена. Потом бы я поставил дату публикации, а PurchaseDate и AvailableCount однозначно бы выносил в другие типы, поскольку до этого было лишь описание "товара" — статическая информация, а дата покупки и количество доступных книг — это динамическая характеристика системы.

К сожалению, тут довольно сложно выделить точное правило, которому будет легко следовать. Я бы предложил попробовать посмотреть на код со стороны его читателя: мы читаем код сверху вниз. Как сгруппировать и расположить поля таким образом, чтобы было очевидно, что в этом наборе свойств/полей является наиболее важным, а что — второстепенным? Какие поля лучше рассматривать совместно, а какие всегда будут анализироваться отдельно? и т.п.
Re[3]: Порядок параметров в методе (и вообще про порядок членов
От: Sinix  
Дата: 18.04.16 05:49
Оценка:
Здравствуйте, Shmj, Вы писали:

S>>Ну так не делайте много параметров Если даже вам тяжело — остальным-то как?


S>Количество определяется не вашим желанием а бизнес-требованиями.

Ну а обернуть в класс параметров бизнес тоже запрещает? Правило большого пальца: больше 4 параметров уже повод спросить про бардак, больше 8 — точно пора сказать "горшочек, не вари".

SS>Да я не об этом. Вот просто все свойства, допустим их 15 штук. В каком порядке их расположить друг относительно друга? Просто хаотично? Или по алфавиту? Или как?


По сценариям использования, каждую группу — в отдельный #region.
Например, точно не стоит смешивать свойства, которые заполняются при создании объекта и свойства, которые отображают текущее состояние (аля HasValue).


Внутри группы — по приоритету. Те свойства, что вы считаете важнее — вверх, бесполезную мелочёвку — вдаль.
Re[3]: Порядок параметров в методе (и вообще про порядок чле
От: pagid Россия  
Дата: 18.04.16 06:26
Оценка:
Здравствуйте, Shmj, Вы писали:

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

В этом примере я бы расположил так
Автор, Название, ДатаИздания, ДоступныйОстаток

S>Не кажется ли вам, что сначала нужно расположить Id, книги, а не в середине.

Да.
S> Потом желательно Name. А может Author? Вот как тут понять?
Без разницы. Что тебе кажется первостепенным в тот момент, потом может поменятся, но это неважно.

S> А потом что первым AvailableCount или PublishDateTime?

PublishDateTime раньше, это первичный признак книги.

S>Хотелось бы не думать об этом а действовать по строгому алгоритму.

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

S> Ведь не всегда однозначно что должно быть первым а что вторым...

Это нормальное явление, можно доверится интуиции.

S> Или вообще по алфавиту делать?

Нет
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re[3]: Порядок параметров в методе (и вообще про порядок чле
От: Sinix  
Дата: 18.04.16 07:00
Оценка: +1
Здравствуйте, Shmj, Вы писали:

Опс, пример не заметил. SergeyT расписал, у меня тот же порядок свойств получается, дополню комментариями.
class Book
{
    // Служебные поля
    public long Id { get; set; }
    
    // Ключевые поля (не в смысле уникальности, а в смысле, что их достаточно 
    // чтоб понять, о чём идёт речь).
    public string Author { get; set; }    
    public string Name { get; set; }
    public string Description { get; set;}
    
    // Текущее состояние
    public DateTime PublishDateTime { get; set; }
    public DateTime PurchaseDateTime { get; set; }    
    public int AvailableCount { get; set; }
}


Понятно, что это просто пример, но в продакшне такую структуру данных делать точно не надо (если речь не о рид-онли view конечно). Отхватите кучу весёлых моментов при
Отредактировано 18.04.2016 7:02 Sinix . Предыдущая версия .
Re[2]: Порядок параметров в методе (и вообще про порядок членов)
От: Sinix  
Дата: 18.04.16 07:04
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>+1. Со мной тоже периодически такое происходит!

Оффтоп

Можешь глянуть вот этот
Автор: Sinix
Дата: 01.04.16
вопрос? Не ради спора, действительно интересно.
Re: Порядок параметров в методе (и вообще про порядок членов)
От: Sinatr Германия  
Дата: 18.04.16 07:18
Оценка:
Здравствуйте, Shmj, Вы писали:

S>В каком порядке лучше писать параметры в методе? Видимо лучше по смыслу, чем по алфавиту. Но какой лучше принцип применить? По очереди появления в теле метода? По важности (менее важные, опциональные, уже после).


По смыслу конечно же. Думайте о том, как данный метод будет вызываться и какие у него будут перегрузки (method overload).

S>
class Book
{
   public string Author {get; set;}
   public DateTime PublishDateTime  {get; set;}
   public string Name {get; set;}
   public long Id {get;set;}
   public DateTime PurchaseDateTime {get; set;}
   public int AvailableCount {get; set;}
   public string Description {get; set}
}


Вы спросили про метод, а привели класс. К чему? Параметры метода зависят от того, что метод делает. Если метод работает с экземплярами книг, то передавайте ему книгу. Если это внешний класс-помощник (helper) форматирующий имя автора, то он абстрагируется и вообще не имеет ничего общего с Book, тип его параметра будет скорее всего string или новая сущность Author (возможно с implicit/explicit operator to/from string).

Я для себя "открыл" передачу параметров с указанием имени (конструкторы атрибутов так любят делать), в результате "опциональные" параметры можно разместить как угодно, в порядке вероятности их возможного использования, это требует меньше перегрузок, к примеру:

class Log
{
    public static void Add(string tag, string message = "", Exception exception = null, [CallerMemberName] string caller = "",
        DateTime time = default(DateTime), object arg1 = null, object arg2 = null, object arg3 = null, object arg4 = null)
}

// example
Log("SomeTag"); // tag is mandatory, this can be used at beginning of method to simply log what it was called
Log("SomeTag", "Important message"); // most of time it will be used like this
Log("SomeTag", exception: SomeException); // in case or errors
Log("SomeTag", "Important message", exception: SomeException, arg1 = someParameter1, arg2 = someParameter2); // "full" syntax


В общем случае старайтесь требовать минимум обязательных параметров и используйте перегрузки метода для разных сценариев. Все сценарии (перегрузки) могут в свою очередь вызывать private метод с кучей параметров, в этом случае, как вы понимаете, "порядок не имеет значение важна только жизнь" (с) 5th Element
---
ПроГLамеры объединяйтесь..
Re[4]: Порядок параметров в методе (и вообще про порядок членов
От: Shmj Ниоткуда  
Дата: 18.04.16 10:21
Оценка:
Здравствуйте, Sinix, Вы писали:

S>>Количество определяется не вашим желанием а бизнес-требованиями.

S>Ну а обернуть в класс параметров бизнес тоже запрещает? Правило большого пальца: больше 4 параметров уже повод спросить про бардак, больше 8 — точно пора сказать "горшочек, не вари".

А как быть с конструктором класса? Если параметры обязательные -- их нужно вывести в конструктор, чтобы знать что не забыл установить. А конструктор -- это та же проблема с порядком параметров.

S>Внутри группы — по приоритету. Те свойства, что вы считаете важнее — вверх, бесполезную мелочёвку — вдаль.


Так вот об этом и речь -- сложно выделить приоритет. Что важнее название книги или автор? Дата закупки или остаток книг?
Re[4]: Порядок параметров в методе (и вообще про порядок чле
От: Shmj Ниоткуда  
Дата: 18.04.16 10:22
Оценка:
Здравствуйте, pagid, Вы писали:

P>Здравствуйте, Shmj, Вы писали:


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

P>В этом примере я бы расположил так
P>Автор, Название, ДатаИздания, ДоступныйОстаток

Мне нужна удочка а не рыба. Т.е. принцип, по которому нужно сортировать параметры, а не это отдельное решение.
Re[2]: Порядок параметров в методе (и вообще про порядок членов)
От: Sinix  
Дата: 18.04.16 10:28
Оценка:
Здравствуйте, Sinatr, Вы писали:

S>Я для себя "открыл" передачу параметров с указанием имени (конструкторы атрибутов так любят делать), в результате "опциональные" параметры можно разместить как угодно, в порядке вероятности их возможного использования, это требует меньше перегрузок, к примеру:


Вот тут обязательно надо читать вот это. Иначе рано или поздно выстрелит.

Вообще я удивлён, что нашлась хоть одна схема работы с optional args, которая почти не создаёт проблем с бинарной совместимостью. Все остальные варианты рано или поздно подкладывали очень обидный MissingMethodException.
Re[5]: Порядок параметров в методе (и вообще про порядок членов
От: Sinix  
Дата: 18.04.16 10:40
Оценка:
Здравствуйте, Shmj, Вы писали:


S>А как быть с конструктором класса? Если параметры обязательные -- их нужно вывести в конструктор, чтобы знать что не забыл установить. А конструктор -- это та же проблема с порядком параметров.

Решено ещё в первом релизе фреймворка. Как пример см на ProcessStartInfo class.
Для эстетов есть вариант аля SqlConnectionStringBuilder.


S>>Внутри группы — по приоритету. Те свойства, что вы считаете важнее — вверх, бесполезную мелочёвку — вдаль.

S>Так вот об этом и речь -- сложно выделить приоритет. Что важнее название книги или автор? Дата закупки или остаток книг?

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

С точки зрения архитектора — оба варианта ересь, подлежащая сожжению. Подсказка: количество авторов >= 0.
Re[6]: Порядок параметров в методе (и вообще про порядок членов
От: Shmj Ниоткуда  
Дата: 18.04.16 10:56
Оценка:
Здравствуйте, Sinix, Вы писали:

S>>А как быть с конструктором класса? Если параметры обязательные -- их нужно вывести в конструктор, чтобы знать что не забыл установить. А конструктор -- это та же проблема с порядком параметров.

S>Решено ещё в первом релизе фреймворка. Как пример см на ProcessStartInfo class.
S>Для эстетов есть вариант аля SqlConnectionStringBuilder.

Там конструктор с 1-2 параметрами, значения устанавливаются через свойства. Как я вижу -- там не все свойства обязательны.

S>Если танцевать от сценариев использования, то группировка "автор, название" куда удобнее чем "название, автор". Порядок соответствующий.


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

Если будете давать плохие названия или не сможете структурировать порядок свойств/аргументов -- с кодом не возможно будет работать. Но четких критериев нет. Все это уже гуманитарная наука.

S>С точки зрения архитектора — оба варианта ересь, подлежащая сожжению. Подсказка: количество авторов >= 0.


Пример не идеален. В данном случае в графе автор может быть записано 10 разных имен через запятую или же значение null.
Re[7]: Порядок параметров в методе (и вообще про порядок членов
От: Sinix  
Дата: 18.04.16 11:04
Оценка:
Здравствуйте, Shmj, Вы писали:

S>>Решено ещё в первом релизе фреймворка. Как пример см на ProcessStartInfo class.

S>>Для эстетов есть вариант аля SqlConnectionStringBuilder.

S>Там конструктор с 1-2 параметрами, значения устанавливаются через свойства. Как я вижу -- там не все свойства обязательны.

бинго. А дальше ProcessStartInfo передаётся как параметр конструктора Process.
И без него пришлось бы городить 100500 перегрузок new Process().

S>>Если танцевать от сценариев использования, то группировка "автор, название" куда удобнее чем "название, автор". Порядок соответствующий.

S>Получается это и есть главный навык, который не возможно формализовать.
Это не навык, это понимание предметной области. Если для вас нет никакой разницы между автором и датой продажи скажем — как вы будете оценивать более сложные вещи, тот же приоритет требования?


S>Если будете давать плохие названия или не сможете структурировать порядок свойств/аргументов -- с кодом не возможно будет работать. Но четких критериев нет. Все это уже гуманитарная наука.

Это не гуманитарная наука. Обычное понимание предметной области + навык правильно думать при проектировании софта. За последним — к FDG book. Только её надо не зазубривать, а пытаться по примерам понять, как размышляют товарищи, которые таки надизайнили API без серьёзной перетряски работающее уже сколько там лет?



S>>С точки зрения архитектора — оба варианта ересь, подлежащая сожжению. Подсказка: количество авторов >= 0.

S>Пример не идеален. В данном случае в графе автор может быть записано 10 разных имен через запятую или же значение null.
Я ж говорю — ересь
Re[8]: Порядок параметров в методе (и вообще про порядок членов
От: Shmj Ниоткуда  
Дата: 18.04.16 11:37
Оценка:
Здравствуйте, Sinix, Вы писали:

S>>Там конструктор с 1-2 параметрами, значения устанавливаются через свойства. Как я вижу -- там не все свойства обязательны.

S>бинго. А дальше ProcessStartInfo передаётся как параметр конструктора Process.
S>И без него пришлось бы городить 100500 перегрузок new Process().

Дело в том что не все свойства ProcessStartInfo являются обязательными.

Минимально достаточно лишь установить FileName -- без него будет InvalidOperationException, а не ArgumentNullException. А остальные опциональные или же их установка зависит от сложных условий (если нет -- будет InvalidOperationException).

А как быть когда нужно чтобы все обязательные свойства были установлены?

S>Это не навык, это понимание предметной области. Если для вас нет никакой разницы между автором и датой продажи скажем — как вы будете оценивать более сложные вещи, тот же приоритет требования?


Однако же вопросы возникают и некоторые дают готовые рецепты: http://programmers.stackexchange.com/questions/101346/what-is-best-practice-on-ordering-parameters-in-a-function
Re[9]: Порядок параметров в методе (и вообще про порядок членов
От: Sinix  
Дата: 18.04.16 11:50
Оценка:
Здравствуйте, Shmj, Вы писали:

S>>бинго. А дальше ProcessStartInfo передаётся как параметр конструктора Process.

S>>И без него пришлось бы городить 100500 перегрузок new Process().

S>А как быть когда нужно чтобы все обязательные свойства были установлены?

Точно так же как и с обычной передачей параметров — проверять в конструкторе основного типа. Вы ведь эти проверки делаете?

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


S>>Это не навык, это понимание предметной области. Если для вас нет никакой разницы между автором и датой продажи скажем — как вы будете оценивать более сложные вещи, тот же приоритет требования?

S>Однако же вопросы возникают и некоторые дают готовые рецепты: http://programmers.stackexchange.com/questions/101346/what-is-best-practice-on-ordering-parameters-in-a-function

Эти рецепты — просто выжимка из очень простого правила:

Framework Design Principle: Frameworks must be designed starting from a set of usage scenarios and code samples implementing these scenarios.


По сути, вся остальная FDG book про то, как надо думать, чтобы это правило соблюдалось автоматом, без необходимости писать код для проверки сценариями использования.
Re[10]: Порядок параметров в методе (и вообще про порядок членов
От: Shmj Ниоткуда  
Дата: 18.04.16 11:55
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Точно так же как и с обычной передачей параметров — проверять в конструкторе основного типа. Вы ведь эти проверки делаете?

S>Сам код проверки можно спрятать под капот класса параметров, вызывать из конструктора основного класса.

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

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