Является ли хорошей практикой хранить имена свойств в общедоступной постоянной строке?

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

public const string StudentCountPropertyName = "StudentCount";
public int StudentCount {get;set;}

Например: подумайте о привязке данных; где вы явно вводите имя свойства в атрибуте DataFieldName.

Или это не очень хорошая идея и есть способ лучше и безопаснее?


person pencilCake    schedule 14.07.2011    source источник
comment
как вы предлагаете воспользоваться существованием этих констант?   -  person Adam Ralph    schedule 14.07.2011
comment
Представьте что-то вроде: DataFieldName=‹%=StudentCollection.StudentCountPropertyName %›   -  person pencilCake    schedule 14.07.2011


Ответы (6)


ИМХО, всегда полезно переместить любые «магические строки» в константы.

Вы можете рассмотреть возможность использования лямбда-выражений для «выбора» ваших свойств, например:

GetDataFieldName(studentCollection => studentCollection.Count)

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

person Jakub Konecki    schedule 14.07.2011
comment
насколько безопасно, если свойство будет встроено? - person Valentin Kuzub; 14.07.2011
comment
@ValentinKuzub: встраивание не меняет семантику метода, поэтому невозможно, чтобы оно могло снизить безопасность или доступность объекта. Встраивание — это строго JIT-оптимизация, а не то, о чем вы как программист должны беспокоиться. - person Cody Gray; 14.07.2011
comment
если свойство является встроенным, разрешение имени свойства на основе отражения не удастся, это моя проблема - person Valentin Kuzub; 14.07.2011
comment
@Валентин - if property is inlined reflection based property name resolution would fail - ты уверен? Я не думаю, что оптимизация IL повлияет на отражение. - person Jakub Konecki; 14.07.2011
comment
оптимизация встроенного свойства IL означает, что все виды использования свойства int CountPropName{get{return m_Count;}} заменяются на 'return m_Count;' как видите, CountPropName полностью исчезнет из оптимизированной сборки, если такая оптимизация будет иметь место. Можете ли вы гарантировать, что ваши свойства не будут встроены? - person Valentin Kuzub; 14.07.2011
comment
@Valentin - я не думаю, что встраивание свойств работает именно так. Я всегда считал, что встраивается именно вызов свойства, а не само определение, поэтому var a = new MyClass().Property; становится var a = new MyClass().m_property;. Думаю задам отдельный вопрос. - person Jakub Konecki; 14.07.2011
comment
@Valentin - stackoverflow.com/ вопросы/6691823/ - person Jakub Konecki; 14.07.2011
comment
действительно ваше право. если вы не попытаетесь получить имя свойства, используя отражение из внутреннего свойства, встраивание не удалит метаданные свойства, и ваш метод будет безопасным - person Valentin Kuzub; 14.07.2011

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

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

Использовать такой подход или нет вы должны решать сами.

person Andrew Orsich    schedule 14.07.2011

Я думаю, что это обычная практика — помещать эту «магическую строку» или «магические числа» в какое-то строго типизированное хранилище.

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

Например, вызовы notifypropertychagned могут быть реализованы с помощью атрибута, реализованного с помощью инфраструктуры aop, например PostSharp .

[NotifyChange]
public int Value {get;private set}

У этих инструментов также есть некоторые недостатки, но я думаю, что есть сценарии, в которых они могут сэкономить вам много работы.

person Boas Enkler    schedule 14.07.2011

Я не знаю, полностью ли я понимаю ваш вопрос, но если я правильно понимаю, я бы использовал для этого атрибут, примером может быть использование ColumnAttribute в Linq, которое вы используете для сопоставления свойства с определенным столбцом в базе данных (http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.columnattribute.dbtype.aspx), как в этом примере:

[Column(Storage="ProductID", DbType="VarChar(150)", CanBeNull=False)]
public string Id { get; set; }

И я бы никогда не использовал DataFieldName, я бы привязал DataBind к строго типизированным объектам (и, конечно, также сделал бы интерфейс к классу, который использует указанное выше свойство, чтобы я мог легко изменить реализацию в будущем;))

person Martin Odhelius    schedule 14.07.2011

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

Однако изменение имени столбца базы данных и имени свойства объекта подразумевает изменение вашей концептуальной модели данных. Как вы думаете, как часто это будет происходить? На ранних стадиях проекта, когда концептуальное моделирование и реализация выполняются командой разработчиков параллельно, это может быть довольно плавным, но как только начальное концептуальное моделирование выполнено (независимо от того, формализовано ли это сознательно или просто органично), это обычно довольно сложно. маловероятно, что такие фундаментальные вещи изменятся. По этой причине я думаю, что это относительно необычно, и этот метод будет продуктивным только в крайних случаях.

person Adam Ralph    schedule 14.07.2011
comment
Опять же, константы не предназначены для изменения, как всегда. Изменение общедоступной константы нарушает бинарную совместимость - person Dyppl; 14.07.2011
comment
Очень верно, но это актуально только при отправке «опубликованных» сборок, то есть для использования третьей стороной, которая может или не может перекомпилировать свой код после добавления новой версии вашей сборки. Для сборок внутреннего использования возможно изменение константы. Я согласен, однако, что это все еще несколько неправильное использование понятия «константа». - person Adam Ralph; 15.07.2011

Абсолютно. Это хорошая идея.

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

Делая это таким образом, вы избежите повторной компиляции, если какая-либо база данных, POCO или что-то еще изменится, и, как и в более новых версиях Visual Studio, таких как 2010, вы можете указать ему генерировать настройки с «общедоступной» доступностью, вы можете совместно использовать строго типизированные настройки с любой сборкой, которая ссылается на ту, которая их содержит.

В конце концов, я бы изменил ваш код на DataBindingSettings.StudentCountPropertyName вместо константы.

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

Прочтите эту статью MSDN, чтобы узнать больше о настройках приложения:

person Matías Fidemraizer    schedule 14.07.2011