Реалізація стандартної архітектури в Visual C # (Sharp)

Серед розробників програмного забезпечення останнім часом широко обговорюється тема угоди правіше конфігурації. Це обговорення пряли особливо активну форму з виходом інфраструктури Ruby on Rails (http://wwwrubyonrailsorg/) Інфраструктура Ruby on Rails (або просто Rails) являє собою інструмент, що дозволяє швидко створювати Web-сторінки, предоавляющіе корисну функціональність Більшість розробників постійно шукає способи для більш швидкого виконання завдань, і Rails є одним з тихий способів

Багато приписують успіх Rails його застосування концепції традиція правіше конфігурації. Інші кажуть, що це завдяки мові Ruby А треті тому, що Ruby є професійним продуктом

Повернемося до проблеми динамічного завантаження коду або, вірніше, динамічному іолненію коду Як ви думаєте, скільки програміст повинен знати і скільки він повинен припускати Розглянемо наступний код:

interface IDefinition   { } void Dolt(IDefinition def) {

/ / Виконується небудь операція з def

}

У коді ми бачимо інтерфейс IDefinition і метод Doit про з параметром типу IDefinition Це створює контракт, за яким при виклику Doit про йому необхідний передати примірник типу IDefinition

Чи буде правильним припустити, що динамічне завантаження типу може удоетворіть вимоги контракту для Doit о Чи можемо ми припускати, що тип взагалі здатний поддержіват Ь IDefinition

Згідно концепції угоди правіше конфігурації здійснюється спроба створити скупчення автономної функціональності, яка може сама забезпечити свої вимоги Для даної автономної функціональності може знадобитися застосування конфігураційного файлу або інших збірок Але що їй не потрібно, так це директива з вихідним кодом, який прямим чином вказує їй, що робити і коли

Розглянемо ситуації в будь-якому офісі або в будь-який інший робочому середовищі Роводітель, замість того щоб вказувати підлеглим, що робити на кожному шу, дає тільки завдання, а в виконанні даного завдання передбачає наявні у кожного співробітника знання, доповнені знаннями його колег Покладатися на свої знання і добре, і погано Добре тому, що обмежується число іспоітелей, погано тому, що може бути обраний неправильний підхід

Наступний код є прикладом угоди:

interface ICommand { void Run()

}

ConfigurationLoaderInstanceLoad() IDefinition definition =

ConfigurationLoaderInstanceInstantiate&ltICommand&gt(&quotImpll&quot)

definitionRun()

Код виконує якийсь інший код за допомогою методу Run про і не має ні Повертаючись значення, ні вихідних параметрів Викликає код сподівається, що іспоеніе викликається коду буде благополучним У цьому і полягає суть концеіі угоди правіше конфігурації – Викликає код сподівається, що все буде добре Нагадую, що це аналогія співробітництва рівних одиниць

За великим рахунком, угода працює досить добре, тому що система на основі угод легше піддається розширенню і супроводу, т к містить

менше робочих компонентів Для будь-якої складної системи застосуємо принцип: чим менше робочих компонентів, тим краще Але зворотною стороною цього являея необхідність, щоб адміністратор знав, які маються робочі компоненти

Люди мають схильність до того, щоб все було конфігурованим, і не оставлт ніяких рішень компютерній програмі Але чи буде конфігурація раба, залежить від того, як вона написана В архітектурі угод викликається функціональність буде приймати рішення з питань, які вона вважає потрібними

Прикладом конфігурації може служити наступний код: [ConfigurationProperty (typename, IsRequired = true)] public string TypeName {

get {

return (string)base[_propTypeName]

}

}

Код повинен бути вам знайомим, т к він схожий на конфігураційний код, рамотренний раніше Але в цьому коді занадто багато обмежень, і для нього требтся занадто багато робочих компонентів Його можна спростити в наступний код (яка не скомпіліруется, т к ми не можемо змінити кодову базу библиоте NET):

[ConfigurationProperty()] public string TypeName {

get {

return (string)base[_propTypeName]

}

}

Різниця між цими двома фрагментами коду полягає в відсутніх парамеах в атрибутах NET в другому фрагменті Параметри не є обовязковими, Т К ВОНИ вже оголошені членом даних propTypeName, і ми можемо іспользать ідентифікатор властивості в якості цієї додаткової інформації Таким чином, ідентифікатор властивості TypeName можна було б використовувати в Качесов атрибута XML

Деякі можуть доводити, що наявністю перехресного посилання між ідентіфатором властивості і ідентифікатором конфігурації ми створюємо жорстко закодіранную залежність Це законний аргумент Але чи є припущення, º ться робиться в коді, розумним припущенням Чи буде надмірним сказати, що ідентифікатор властивості є імям атрибута XML Ні, не буде, і разрабоікі Ruby on Rails сказали те ж саме, коли створювали свою архітектуру

Тепер розглянемо можливість вказувати, чи є конфігураційний ЕЛЕНТ необхідним Роблячи це, ми можемо уникнути виключення далі в виконанні

Але думайте в більш великому контексті Атрибут NET isRequired обрабативаея при запуску програми При компіляції коректність конфігураційного файлу не перевіряється, тому єдине, що робить isRequired, – Це создт виняток на більш ранньому етапі Можливо, ви хочете уникнути помилок Вренна виконання, які могли б викликати фатальний збій програми Я не даю, що це буде великою вигодою, але впевнений, що багато хто не погодиться зі мною тому рішення, чи використовувати властивість isRequired, приймається кожним заможно

ПРИМІТКА

Метою архітектури за угодою є дозволити максимальне числ про допеній, не жертвуючи більш високою метою додатки Створення гарної архітектури за угодою – завдання не з легких, т к для цього потрібно повне розуміння е пребності розробників і користувачів програми Моє практичне правило – спочатку вирішити проблему, а потім думати, що повинно бути налаштоване, а що залишено за угодою

Динамічне завантаження базового класу або типів інтерфейсу

У цій главі розглядаються дві категорії динамічно завантажується коду Першою категорією є тип, який реалізує інтерфейс (implementation і IDefinition) Другою категорією є клас, похідний від іншого класу (LoaderSection і configurationSection) Кожен підхід має свої преімущтва і недоліки, але для обох застосовно наступне правило

Що використовувати, інтерфейс або клас, залежить від того, скільки відповідальності ви хочете делегувати реалізації У прикладі обробки конфігурації інфртруктура NET конкретно вказувала, що єдиною відповідальністю дініческі загружаемого класу є вказівка, які ідентифікатори необхідний обробити Як витягати значення ідентифікаторів і перетворювати їх у типи NET, є відповідальністю базового класу

Коли при створенні екземпляра типу використовується інтерфейс, ми делегуємо весь контроль динамічно створеному екземпляру типу Викликає код прямо Говіт: Ось твій контракт Як ти його виконаєш – твоя справа Тільки забезпеч, щоб контракт був виконаний належним чином . Делегуючи відповідальність, ми, в певному сенсі, напрошуємося на неприємності, т к розробники можуть реалізувати контракт неправильно

Інші фактори, такі як продуктивність і ресурси, також відіграють роль, але я думаю, що вони не так важливі, як розуміння єдиного правила делегіровія відповідальності

Джерело: Гросс К С # 2008: Пер з англ – СПб: БХВ-Петербург, 2009 – 576 е: ил – (Самовчитель)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*