Tips n Tricks
Atom
1/20/2011
Mikhail Sukhov


Постоянно смотрю на изменяющийся код. Весь поток контролировать не могу, поэтому выбираю некоторые места по принципу Медведь на рыбалке в период нереста. Далее, привожу что увидел и как бы изменил. Рекомендую смотреть всем (даже если свой код не увидели), чтобы и самому учиться и не допустить в будущем:

  1. ODE0� Тут лучше использовать ключевое слово var
foreach (var pair in _sections)
  1. ODE2� С помощью Ecng.Common пишется короче
pair.Value.Join(Environment.NewLine)
  1. ODE4� Тут или область видимости должна быть private или название должно быть SectionName.
  2. ODE5� С помощью Ecng.Common пишется короче
"{0}={1}".Put(key, value)
  1. ODE7� Лучше проверить через Contains.
  2. ODE8� Старайтесь минимизироваться перехват исключений. В том случае это решается через простую проверку на существование в коллекции.
  3. ODE9� Я бы заменил на ArgumentException. Он как то более осмысленный.
  4. Не пишите Decimal, Int64, String или Single. Понятно, что это межъязыковое название. Но лучше использовать то, что родное для C#.
  5. ODE10� Стиль именования как в Win32 API. Последний умер де факто много лет назад, наследие его живет и по сей день.[biggrin]
  6. Добавляйте xml комментарии к самим классам, а не только его членам (видел в некоторых местах через // что есть совсем не то). И не забывайте про русский язык. В конце предложения ставится точка.
  7. Пользуйтесь R#. Он показывает допущенные ошибки и предупреждает заранее о неправильном коде.

Tags:


Thanks:


1 2  >
aspirant

Avatar
Date: 1/20/2011
Reply


Mikhail Sukhov: [*]``` _sections[_sectionNames.IndexOf(sectionName)];

> Лучше проверить через Contains.
> [*]```
try
{
  ....
}
catch (KeyNotFoundException ex)
{
  throw new KeyNotFoundException(String.Format("Неопознанный раздел конфиг-файла: {0}", sectionName), ex);
}

Старайтесь минимизироваться перехват исключений. В том случае это решается через простую проверку на существование в коллекции.

Большинство комментариев относится ко мне. Все поправил за исключением верхнего куска. Вот мое мнение: давно на каком-то MS'ском блоге читал рекомендацию: если в большинстве случаев ключи будут находиться, лучше сразу возвращать значение через метод this[TKey key] и перехватывать неопознанные ключи через исключение. Если вероятность исключения велика, лучше это делать через метод Contains. Это кусок кода написан в protected методе, к которому обращается только мой плазовский код. Входящие значения ключей заранее известны и контролируются, т.е. вероятность ненахождения ключей мала.

Михаил, за вами, как за менеджером проекта, последнее слово.

Thanks:

Mikhail Sukhov

Avatar
Date: 1/20/2011
Reply


aspirant: Большинство комментариев относится ко мне.

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

aspirant:

Mikhail Sukhov: [*]``` _sections[_sectionNames.IndexOf(sectionName)];

> > Лучше проверить через Contains.
> > [*]```
try
{
  ....
}
catch (KeyNotFoundException ex)
{
  throw new KeyNotFoundException(String.Format("Неопознанный раздел конфиг-файла: {0}", sectionName), ex);
}

Старайтесь минимизироваться перехват исключений. В том случае это решается через простую проверку на существование в коллекции.

Вот мое мнение: давно на каком-то MS'ском блоге читал рекомендацию: если в большинстве случаев ключи будут находиться, лучше сразу возвращать значение через метод this[TKey key] и перехватывать неопознанные ключи через исключение. Если вероятность исключения велика, лучше это делать через метод Contains.

Тут не столько дело в перехвате и в Contains, сколько в сложности конструкции ``` _sections[_sectionNames.IndexOf(sectionName)];

Еще раз посмотрел. А почем бы сразу было не сделать Dictionary?

> **[aspirant](@message(5540)):**
> Это кусок кода написан в **protected** методе, к которому обращается только мой плазовский код. Входящие значения ключей заранее известны и контролируются, т.е. вероятность ненахождения ключей мала.

Насчет модификаторов доступа. Есть подозрение что они неправильно используются. Можете привести их описание применительно к случаям использования - когда какой использовать?
Thanks:

aspirant

Avatar
Date: 1/20/2011
Reply


Mikhail Sukhov: Тут не столько дело в перехвате и в Contains, сколько в сложности конструкции ``` _sections[_sectionNames.IndexOf(sectionName)];

> Еще раз посмотрел. А почем бы сразу было не сделать Dictionary?

Вы правы: что я действительно здесь намудрил.  Сегодня сведу все в Dictionary.

> **[Mikhail Sukhov](@message(5541)):**
> > **[aspirant](@message(5540)):**
> > Это кусок кода написан в **protected** методе, к которому обращается только мой плазовский код. Входящие значения ключей заранее известны и контролируются, т.е. вероятность ненахождения ключей мала.
> 
> Насчет модификаторов доступа. Есть подозрение что они неправильно используются. Можете привести их описание применительно к случаям использования - когда какой использовать?

protected может использоваться только классами-наследниками, ну и самим классом тоже.  Снаружи он не виден.  Я имел в виду, что у меня есть класс ConfigParser.  От него наследует класс ClientRouterConfigParser, который и запрашивает информацию, передавая ключи.
Thanks:

Mikhail Sukhov

Avatar
Date: 1/20/2011
Reply


aspirant: protected может использоваться только классами-наследниками, ну и самим классом тоже. Снаружи он не виден. Я имел в виду, что у меня есть класс ConfigParser. От него наследует класс ClientRouterConfigParser, который и запрашивает информацию, передавая ключи.

Все ок. Я не увидел наследования. Но все равно, на будущее. Стиль именования протектем полей такой же как и паблик. Потому как смысл у них почти одинаковый.

Thanks:

aspirant

Avatar
Date: 1/21/2011
Reply


aspirant:

Mikhail Sukhov: Тут не столько дело в перехвате и в Contains, сколько в сложности конструкции ``` _sections[_sectionNames.IndexOf(sectionName)];

> > Еще раз посмотрел. А почем бы сразу было не сделать Dictionary?
> 
> Вы правы: что я действительно здесь намудрил.  Сегодня сведу все в Dictionary.

Только что закоммитил исправленный файл с классом ConfigParser.  Идея такова: это базовый класс, который умеет парсить конфиг-файлы в формате Плазы.  Для каждого конфиг-файла создается класс-наследник, который в своем конструкторе заполняет массив SectionNames списком возможных ключей для этого файла.  Пока я только создал класс ClientRouterConfigParser, который настраивает главный конфиг-файл роутера Плазы client_router.ini.  Я пока не разобрался, нужно ли будет настраивать другие конфиги.
Thanks:

Mikhail Sukhov

Avatar
Date: 1/21/2011
Reply


aspirant: Только что закоммитил исправленный файл с классом ConfigParser. Идея такова: это базовый класс, который умеет парсить конфиг-файлы в формате Плазы. Для каждого конфиг-файла создается класс-наследник, который в своем конструкторе заполняет массив SectionNames списком возможных ключей для этого файла. Пока я только создал класс ClientRouterConfigParser, который настраивает главный конфиг-файл роутера Плазы client_router.ini. Я пока не разобрался, нужно ли будет настраивать другие конфиги.

Это хорошо. Только зря вы убрали метод FindSection. Вообще лучше по максимуму переменные делать private и доступ к ним или через методы или через свойства. Лучше через методы, чтобы базовый класс делал базовую работу, а не просто отдавал свое состояние дочерним.

Thanks:

Mikhail Sukhov

Avatar
Date: 1/21/2011
Reply


Еще список того, что может пригодиться:

  1. ODE0� можно писать короче:
var myNumber = myString.To<int>();
  1. ODE2� можно писать короче:
if (arg.IsEmpty())
Thanks:

Mikhail Sukhov

Avatar
Date: 1/21/2011
Reply


_dataStream.StreamLifeNumChanged += new IP2DataStreamEvents_StreamLifeNumChangedEventHandler(OnStreamLifeNumChanged);

можно писать короче:

v_dataStream.StreamLifeNumChanged += OnStreamLifeNumChanged;
Thanks:

Mikhail Sukhov

Avatar
Date: 1/30/2011
Reply


if (MyEvent != null)
	MyEvent();

Проверка на null - это правильно. Но на следующей строчке MyEvent может стать null (в другом потоке произошла отписка от события) и будет NullReferenceException. Решается через доп переменную:

var evt = MyEvent;
if (evt != null)
	evt();

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

MyEvent.SafeInvoke();
Thanks:

Mikhail Sukhov

Avatar
Date: 3/18/2011
Reply


int и Int32 - это алиасы. так же для bool и Boolean и т.д. Выражение вида:

if (type == typeof(bool) || type == typeof(Boolean))

эквивалентно:

if (type == typeof(bool))
Thanks:
1 2  >

Attach files by dragging & dropping, , or pasting from the clipboard.

loading
clippy