Здравствуйте, Нахлобуч, Вы писали:
Н>Пятница, можно и подискутировать. Н>Кто какой способ предпочитает и почему?
По мне лучше всего — почти как последний, но вынести в отдельный класс UrlHelper или, с тем чтобы при необходимости можно было использовать и в других местах, кроме статей (файлы может, или генераторы ссылок, или какие-то тесты которым надо достучаться до статьи и подобное).
В остальном, я бы сказал, что если метод занимается конвертацией, то у него должна быть сигнатура
X ConvertToX( Y y );
Статическая либо не статическая в зависимости от того, нужен ли доступ к полям класса. Предпочтительнее статический (сразу видно что нет неочевидных зависимостей), но без фанатизма. Второй момент выбора статика или нет — есть ли желание покрыть юнит-тестами с изоляцией этого метода. Тогда не статический и виртуальный чтобы можно было подменить заглушкой.
А если он просто именно инициализирует поля, исходя из каких-то данных, то это void InitValues( с параметрами или без ). При этом, мне не очень-то нравится, если часть полей проставляется в одном методе (тут — в конструкторе), а другая — в другом (тут — ConvertTitleToSlug() ) и при этом жить они могут только вместе. Лучше уж или там или там.
Здравствуйте, Нахлобуч, Вы писали:
Н>Тот факт, что это конструктор -- не принципиально
Принципиально.
Первые два способа не подходят, потому что требуют убрать атрибут readonly у полей.
Третий получше, но нарушает Constructor Design.
Поэтому я бы сделал фабричный метод:
public sealed class Article
{
private readonly string _title;
private readonly string _slug;
private Article(string title, string slug)
{
Debug.Assert(title != null);
Debug.Assert(slug != null);
_title = title;
_slug = slug;
}
public static Article Create(string title)
{
if (title is null)
throw new ArgumentNullException(nameof(title));
string slug = title.ToLowerInvariant().Replace(" ", "-", StringComparison.Ordinal);
return new Article(title, slug);
}
}
Н>class Article
Н>{
Н> string title;
Н> string slug;
Н> // Тот факт, что это конструктор -- не принципиально
Н> public Article(string title)
Н> {
Н> this.title = title;
Н> // Так?
Н> ConvertTitleToSlug();
Н> // Или так?
Н> ConvertTitleToSlug(title);
Н> // Или вовсе вот так?
Н> slug = ConvertTitleToSlug(title);
Н> }
Н>
3-й, static, лучше, ибо его можно отдельно и протестировать, без необходимости создавать объект. Выше уже отметили, что не следует злоупотреблять сложной логикой в конструкторе, хотя сам этим грешу иногда.
Здравствуйте, Нахлобуч, Вы писали:
Н>Кто какой способ предпочитает и почему?
Предпочитаю вынести такой метод в другой класс-конвертер или сделать свободной функцией. Потому что единственная ответственность. Она, конечно, не догма, но в данном случае расходы мизерные.
Исключение — методы, которые конвертируют в/из собственного класса, но здесь не тот случай.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.