Подтвердить что ты не робот

Juval Lowy С# Вопросы стандартов кодирования

Мне нравится и очень рекомендую Juval Lowy's - Стандарт кодирования С#. Juval явно избегает логического обоснования для каждой директивы, чтобы поддерживать стандартную плотность (см. Предисловие). Тем не менее, есть несколько директив, для которых я нахожу себя любопытным относительно обоснования.

Каково конкретное обоснование следующих директив из стандарта Lowy С#?
Надеюсь, на них есть твердые (не субъективные) ответы.

1.13 Избегайте полных имен типов. Вместо этого используйте инструкцию "using".
Это проблема производительности? Иногда мне нужен только один экземпляр полного имени и добавление использования кажется тяжелым.

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

2.19 Избегайте определения настраиваемых классов исключений
Каковы соображения по минимизации их числа? (Далее он дает рекомендации, если вы их определяете (в 2.20).)

2.29 Избегайте использования тернарного условного оператора
Слишком сложно для читателя переварить или другие соображения?

2.31 Избегайте вызовов функций в булевых условных операторах. Назначьте локальные переменные и проверьте их.
Я не думаю, что я это делаю, но мне любопытно... почему бы и нет?

2.47 Избегайте интерфейсов с одним элементом.
Потому что всегда/обычно предпочтительнее делать что? Один интерфейс метода работает, когда?

2.53 Предпочитаете использовать явную реализацию интерфейса
Зачем? Кроме того, Джон Скит здесь не согласен.

Спасибо заранее! Роберт

4b9b3361

Ответ 1

Очевидно, что я не Juval, но я могу нанести удар по этим

1.13 Избегайте полных имен типов. Вместо этого используйте инструкцию "using".

Производительность здесь не может быть проблемой. Я уверен, что проблема в читаемости.

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

public delegate void Foo1();
public delegate void Foo2(int val);

public void Foo()
{
    Foo1 first = delegate { Console.WriteLine("Hello world"); };
    Foo2 second = delegate { Console.WriteLine("Hello world"); };
    Foo1 third = delegate() { Console.WriteLine("Hello world"); };
    Foo2 fourth = delegate() { Console.WriteLine("Hello world"); }; // does not compile
}

Без парнеров анонимный делегат может быть применен к любому делегату. С помощью parens вы конкретно указываете подпись делегата. Предпочитайте второй синтаксис, если вам действительно не нужна гибкость.

2.19 Избегайте определения настраиваемых классов исключений

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

2.29 Избегайте использования тернарного условного оператора

Это читаемость и расширяемость. Я не согласен, но это стандартный религиозный бой.

2.31 Избегайте вызовов функций в булевых условных операторах. Назначьте в локальные переменные и проверьте их.

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

2.47 Избегайте интерфейсов с одним элементом.

"Избегайте", как бы "предпочитают", он просто говорит дважды, прежде чем это сделать. Если у вас только один участник, действительно ли интерфейс действительно моделирует что-то полезное и полное в вашем дизайне? Довольно редко, чтобы иметь класс только с одним членом, серьезно подумайте о том, почему ваш интерфейс какой-либо другой.

2.53 Предпочитаете использовать явную реализацию интерфейса

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

Ответ 2

2.29 Избегайте использования тернарного условного оператора У меня нет проблем с "простым" использованием тернарного оператора, но он рекомендовал не использовать его вложенным образом:

// This is fine
x := (conditionA) ? true_resultA : false_resultA;

// This would probably be clearer using if-then-elseif
x := (conditionA) ? 
       ((conditionA1) ? true_resultA1 : (condition2) ? true_result2 : false_result2) :
       ((conditionA2) ? true_resultA2 : false_resultA2);

Ответ 3

1.26 относится к синтаксису pre-lambda delegate { }.

// #1 Empty parenthesis on parameterless-anonymous methods would be:
delegate() { }
// #2 ... anonymous method could have been used on any delegate, is:
delegate { }

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

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

Ответ 4

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

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

Например:

2.29 Избегайте использования тернарного условного оператора

У меня нет проблем с тернарными выражениями, как таковыми, но путем написания кода, такого как: int result = CheckMethod()? OnTrueDoThis(): OnFalseDoThat()... вы говорите: "У меня есть условие, что если true (или false), вы можете сделать одно и только одно." Вся конструкция препятствует расширяемости. Вы должны воссоздать конструкцию (с выражением if..else).

Аналогично...

2.31 Избегайте вызовов функций в булевых условных операторах. Назначить локальные переменные и проверить их.

Вы вызвали функцию и существенно "отбросили" результаты для дальнейшего использования. Если эта информация понадобится позже, либо функция должна быть вызвана снова, либо структура кода должна быть переписана. Это также упростило бы проверку или протоколирование результатов (для будущей отладки).

Enjoy,

Роберт К. Картайно

Ответ 5

Относительно 1.13 (Избегайте полных имен типов типов. Вместо этого используйте инструкцию "using" ):

Это может быть немного больше, чем читаемость. Если у вас слишком много записей в начале файла, у вас есть класс, который связан с классами из слишком большого пространства имен.

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

Ответ 6

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

1.13 Избегайте полных имен типов. Вместо этого используйте инструкцию "using".

читаемость. Это должно быть труднее читать код, когда вам нужно читать полностью квалифицированные имена типов.

2.19 Избегайте определения настраиваемых классов исключений

В .NET Framework есть хороший набор исключений, встроенных в систему. Если исключение, которое вы моделируете, зависит от бизнес-домена, вы, вероятно, сможете использовать один из существующих классов исключений.

2.29 Избегайте использования тернарного условного оператора

Я думаю, что это, скорее всего, потому, что он думает, что люди могут не понимать оператора, но я не согласен.

2.47 Избегайте интерфейсов с одним элементом.

Он может предупредить людей о том, что они слишком тонкие интерфейсы. Тем не менее, я бы сказал, наоборот, предупреждая людей о том, чтобы сделать интерфейсы слишком многословными. Если вам когда-либо приходилось иметь дело с ASP.NET MembershipProvider, вы знаете, о чем я говорю.

2.31 Избегайте вызовов функций в булевых условных операторах. Назначьте в локальные переменные и проверьте их.

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

2.53 Предпочитаете использовать явную реализацию интерфейса

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

Ответ 7

Вот некоторые из моих реакций, о которых я смею им ответить:)

1.13 Избегайте полных имен типов. Вместо этого используйте инструкцию "using". Я не согласен. Это, безусловно, не связано с производительностью. Это может привести к повышению удобочитаемости var foo = new Foo() вместо var foo = new MyCompany.MyNamespace.Helpers.Xml.Foo(), но кроме этого - нет.

2.19 Избегайте определения настраиваемых классов исключений Это бессмыслица имхо. Вам следует избегать создания пользовательских исключений, которые происходят из ApplicationException, но нет ничего плохого в пользовательских исключениях (если вы не собираетесь повторно использовать существующие исключения).

2.29 Избегайте использования тернарного условного оператора Я понятия не имею, почему это было бы ориентиром. Я прочитал, что не все люди используют его и не могут его распознать, но это не является веской причиной не использовать полезный оператор.

2.31 Избегайте вызовов функций в булевых условных операторах. Назначьте локальные переменные и проверьте их. Это, по-моему, просто вопрос читаемости.

2.47 Избегайте интерфейсов с одним элементом. Я тоже не согласен. Вы должны избегать "маркерных" интерфейсов, хотя - интерфейсы без маркера, но которые просто служат цели, чтобы что-то было "... ble". Но один метод на интерфейсе мне кажется прекрасным.

Ответ 8

2.29 Тернарный оператор

Для начала, если вы начинаете использовать тернарный оператор, должна быть причина использования тернарного оператора над регулярным if-then-else. Обратите внимание:

if (x == 0) {...} else{...} //A set of statements demand a regular If-then-else

//A simple assignment can be handled by the ternary operator
y = (x == 0)? 1 : 0 //this is readable and how it should be used


(x==0)? callSomething() : callSomethingElse() //this is NOT how it should be used

Тернарный оператор предназначен для возврата одного из двух значений в зависимости от условного значения, которое он оценивает. Это очень удобно при выполнении FP. Для операторов вызовов, которые не возвращают значение, вы должны вернуться к if-then-else.