Правда ли, что я не должен делать «долго работающие» вещи в аксессоре свойств? - PullRequest
8 голосов
/ 19 мая 2009

А если так, то почему? и что составляет "длительный срок"?

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

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

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

Ответы [ 8 ]

22 голосов
/ 19 мая 2009

Как вы упомянули, это сюрприз для пользователя класса. Люди привыкли делать подобные вещи со свойствами (надуманный пример приведен ниже):

foreach (var item in bunchOfItems)
    foreach (var slot in someCollection)
        slot.Value = item.Value;

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

foreach (var item in bunchOfItems)
{
   var temp = item.Value;
   foreach (var slot in someCollection)
      slot.Value = temp;
}

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

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

12 голосов
/ 19 мая 2009

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

Кроме того, этот вопрос широко обсуждается в Framework Design Guidelines ; подумайте о том, чтобы забрать копию.

3 голосов
/ 19 мая 2009

Это просто "хорошая практика" - не заставлять методы доступа к свойствам занимать много времени. Это потому, что свойства выглядят как поля для вызывающей стороны и, следовательно, для вызывающей стороны (пользователя вашего API), как правило, предполагают, что нет ничего, кроме "return smth;"

Если вам действительно нужно какое-то «действие» за кулисами, подумайте о создании метода для этого ...

3 голосов
/ 19 мая 2009

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

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

3 голосов
/ 19 мая 2009

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

1 голос
/ 19 мая 2009

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

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

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

1 голос
/ 19 мая 2009

Я не вижу, в чем проблема с этим, если вы предоставляете документацию XML, чтобы Intellisense уведомлял потребителя объекта о том, во что он попадает.

Я думаю, что это одна из тех ситуаций, когда нет единого правильного ответа. Мой девиз: «Говорить всегда почти всегда неправильно». Вы должны делать то, что наиболее целесообразно в любой конкретной ситуации, без учета широких обобщений.

0 голосов
/ 27 мая 2009

Это не имеет прямого отношения к вашему вопросу, но рассматривали ли вы вариант загрузки с однократной загрузкой в ​​сочетании с параметром обновления?

class Example
    {
        private bool userNameLoaded = false;
        private string userName = "";
        public string UserName(bool refresh)
        {
            userNameLoaded = !refresh;   
            return UserName();
        }
        public string UserName()
        {
            if (!userNameLoaded)
            {
                /*
                userName=SomeDBMethod();
                */
                userNameLoaded = true;                    
            }
            return userName;         
        }
    }
...