[Проектирование и рефакторинг, C#, Разработка под Windows] Проектирование на C# глазами первокурсника -> NotePad++ №6

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
15-Фев-2021 18:30

Всем привет, меня зовут Аркадий, я студент НИУ ВШЭ и в данной статье мы с вами поговорим о задании PeerReview №6 NotePad++, а именно об архитектурах, которые подойдут для данного задания и некоторых паттернов.Задание
В данном задании основной задачей является реализация приложения с графическим интерфейсом. Предлагаю не далеко не отходить от темы и сразу же посмотреть на то, что такое архитектуры и как они могут нам помочь в данном случае.
Bнформация из этого поста не покрывает всех существующих архитектур и паттернов, но является вполне достаточной для реализации задания №6
Архитектуры приложенийПод архитектурой мы понимаем архитектурный шаблон проектирования, охватывающий всё приложение или какую-то его часть. Часто такую часть называют модулем. Из этих модулей и строится приложение. Под модулями в данном случае понимаются не C# модули, а архитектурные модули. Им может являться, например, один экран приложения или несколько связанных между собой экранов.Тема архитектур вызывает много споров. Во-первых, у каждого разработчика свое представление о том, какой должна быть хорошая архитектура. Во-вторых, даже если взять какую-то конкретную архитектуру, то вы сможете найти несколько различающихся между собой реализаций. Ну и третья причина заключается в том, что идеальных архитектур не существует. У каждой из них есть преимущества и недостатки. Поэтому при обсуждении архитектурных подходов всегда есть за что поругать любое из решений.Я расскажу лишь о трёх архитектурных решениях, которые считаю самыми подходящими для данного проекта, к тому же они имеют достаточно низкий порок вхождения1. Apple MVCПервая архитектура, которую мы разберем – MVC. Мы сразу сталкиваемся с тем, что под одним названием могут скрываться разные подходы. Например я предлагаю рассмотреть архитектуру Apple MVC, которая чуть лучше стандартной Classic MVC
Шаблон проектирования Apple MVCКак и во многих других архитектурах, название – это аббревиатура. Каждая буква обозначает один из компонентов. Рассмотрим их по порядку.
  • M – Model. Роль модели могут играть как простые классы или структуры, так и сложные сущности, запрашивающие информацию из базы данных или из сети. Модель не знает о существовании UI (user interface). Можно рассматривать ее как ядро приложения, которое можно переиспользовать с другим интерфейсом. Например, использовать одну и ту же модель для версии программы под разные устройства
  • V – View. Вью – это представление. То, что пользователь видит и с чем взаимодействует. Ответственности вью – это отрисовка себя на экране и реагирование на действия пользователя, но оно не содержит логики и просто передает событие в Controller. В качестве представления в С#-приложениях используются Form и его наследники. Одну и ту же вью можно использовать на разных экранах приложения или даже перенести в другое.
  • C – Controller. Это связующее звено между моделью и представлением. Его ответственность заключается в том, чтобы принимать действия пользователя от View, обрабатывать их и в случае необходимости обновлять модель, а при изменении модели обновлять вью. Т.к. контроллеры содержат логику, специфичную для приложения, то их сложно переиспользовать.
Один контроллер не всегда соответствует одному экрану. Их можно вкладывать друг в друга, разбив таким образом большой контроллер на несколько маленьких. Например, можно реализовать TabBarController который будет являться контейнером для нескольких контроллеров. При нажатии на вкладки он просто подменяет один на другой.MVC – хороший выбор для данного приложения. Эта архитектура имеет очень низкий порог вхождения (количество знаний и сил для её реализации). Однако есть одна проблема в реализации MVC от Apple. Они наделили ViewController обязанностью следить за жизненным циклом View. Из-за этого они очень сильно связаны. В итоге контроллер содержит не только обработку модели, но и взаимодействие с вью. Для решения этой проблемы во всех остальных архитектурах ViewController считается частью вью. В нем остается обработка жестов, анимации и прочее взаимодействие с View. А всю остальную логику переносят в другое место. Таким образом мы избегаем так называемого «Massive View Controller»Еще одна важная проблема, которая решается таким образом – сложность тестирования. Если вы хотите проверить какую-то логику, находящуюся в ViewController, то вам придется иметь дело с жизненным циклом вью.2. MVPОчевидным развитием MVC является MVP. Раз ViewController – это часть вью, то вместо него нужно добавить какую-то другую сущность, никак не связанную с View, в результате получаем Presenter.
Шаблон проектирования MVPПолучившаяся схема очень похожа на MVC от Apple. Разница в том, что вся логика, не связанная с представлением, перемещается из ViewController в Presenter.
Обратите также внимание на то, что вью, как и в MVC, пассивная. Presenter передает в нее данные, но сама она их не запрашивает, хотя обращение к презентеру не запрещено. Оно может происходить, например, для вызова обработчика нажатия на кнопку.
3. MVVMMVVM очень похоже на MVP. Разница в том, что вместо презентера в нем используется ViewModel. Вью модель хранит в себе состояние представления. Например, текст на экране или значение поля для ввода. Но в отличие от MVP, вью сама берет данные для отображения. Это можно реализовать разными способами, но часто используется data binding (паттерн в следующей главе). Это подход, при котором один объект следит за состоянием другого. Т.е. вью будет следить за своим значением, хранящимся во ViewModel, и изменять свое отображение при его изменении.
Шаблон проектирования MVVMMVVM и MVP решают проблему большого контроллера и облегчают тестирование. Однако порог вхождения в проекты, написанные на них, немного выше. Особенно это касается MVVM с биндингами, т.к. часто в таких проектах связывание данных используется не только между View и ViewModel. Такой код сложнее понять новичку, а еще сложнее отлаживать.
В данном проекте можно использовать эти или любые другие архитекрутрные решения. Лично я бы советовал использовать MVVM, так как он упростит реализацию настроек и вкладок.
ПаттерныСуществует великое множество паттернов проектирования. Другое их название – шаблоны проектирования.Паттерны – это многократно используемые решения часто встречающихся проблем при разработке. Они помогают писать код, который можно легко понять и использовать повторно. Паттерны помогают создавать слабо связанный код, в котором относительно легко и безболезненно можно заменять компоненты.Мы рассмотрим самые распространенные паттерны, которые можно использовать в данном проекте. Давайте перечислим их:
  • Синглтон (Singleton)
  • Target-Action
  • Наблюдатель (Observer)
  • Команда (Command)
Я намеренно не включил в данные список Делегирование, т.к. считаю, что в данном проекте его использование будет излишним, в силу простоты программы.
В нескольких примерах кода буду использовать Swift, т.к. во-первых я его учу и надо практиковаться, а во-вторых **** я ваш C#, лучше **** *** *** ***** *** **** , чем буду на нём писать не на оценку. Спасибо за понимание.
1. Синглтон (Singleton)Синглтон-паттерн широко используется при разработке программного обеспечения. Он гарантирует, что будет создан только один экземпляр класса и обеспечивает глобальную точку доступа для ресурсов, которые он предоставляет.Применяется, когда нужно создать один и только один объект какого-либо класса на весь жизненный цикл приложения и доступ к которому необходимо получать из разных частей кода.Примером применения этого паттерна является создания класса настроек приложения. Очевидно, что настройки приложения являются единственными в своём роде на всё приложение.Другой пример применения данного паттерна – сервис GPS-навигации. Допустим, нам в приложении нужно отслеживать местоположение пользователя. В телефоне установлен единственный модуль GPS, и определять текущие координаты умеет только он. Ресурсы, которые предоставляет этот модуль, можно использовать совместно. В этом случае можно создать один глобальный синглтон-объект. И этот объект уже внутри себя будет использовать экземпляр класса LocationManager, предоставляющий единственную точку входа ко всем сервисам GPS-модуля.
class NetworkManager {
  private(set) static var sharedInstance: NetworkManager = {
    let manager = NetworkManager()
    // additional setup code
     return manager
  }()
  private init () {
  }
  func sendRequest() {
    print("sending request")
  }
}
// main program
let networkManager = NetworkManager.sharedInstance
networkManager.sendRequest() // sending request
2. Target-ActionСледующий паттерн, который мы рассмотрим, называется Target-Action. Обычно пользовательский интерфейс приложения состоит из нескольких графических объектов, и зачастую в роли таких объектов используются т.н. элементы управления. Это могут быть кнопки, переключатели, поля для ввода текста. Роль элемента управления в пользовательском интерфейсе довольно проста: он воспринимает намерение пользователя сделать какое-либо действие и дает указание другому объекту обработать этот запрос. Для связи между элементом управления и объектом, который может обработать запрос, и используется паттерн Target-Action. Target-Action – паттерн, в котором объект содержит информацию, необходимую для вызова метода у другого объекта при возникновении некоторого события, например, нажатия кнопки. Информация состоит из двух типов данных: селектора, который идентифицирует вызываемый метод (action), и объекта, чей метод вызывается (target). Остановимся чуть подробнее на том, что такое селекторы.Фактически, селектор – это имя метода объекта или структуры, или уникальный идентификатор, который заменяет имя метода при компиляции исходного кода. Селектор сам по себе ничего не делает. Он просто идентифицирует какой-то метод.Данный паттерн встроен в язык WindowsForm проект, так что в самостоятельной реализации не нуждается3. НаблюдательВ паттерне «Наблюдатель» один объект уведомляет другие объекты об изменениях своего состояния. Объектам, связанным таким образом, не нужно знать друг о друге – это и есть слабо связанный (а значит, гибкий) код. Этот паттерн чаще всего используют, когда надо уведомить «наблюдателя» об изменении свойств нашего объекта или о наступлении каких-либо событий в этом объекте. Обычно наблюдатель «регистрирует» свой интерес о состоянии другого объекта. Когда состояние меняется, все объекты-наблюдатели будут уведомлены об изменении.
Уведомление – это сообщение, отправленное наблюдателям, чтобы оповестить их о каком-либо событии. Уведомления основаны на модели «подписка—публикация». Согласно ей, объект «издатель» (publisher) рассылает сообщения подписчикам (subscribers). Издатель ничего не должен знать о подписчиках.
interface IObservable {
  void AddObserver(IObserver o);
  void RemoveObserver(IObserver o);
  void NotifyObservers();
}
class ConcreteObservable : IObservable {
  private List<IObserver> observers;
  public ConcreteObservable(){
    observers = new List<IObserver>();
  }
  public void AddObserver(IObserver o){
    observers.Add(o);
  }
  public void RemoveObserver(IObserver o){
    observers.Remove(o);
  }
  public void NotifyObservers(){
    foreach (IObserver observer in observers)
      observer.Update();
  }
}
interface IObserver {
  void Update();
}
class ConcreteObserver :IObserver {
   public void Update() {
     // Some Action
   }
}
В данном примере ( к сожалению написанном на c#, т.к. реализация с другими языками отличается существенно ):
  • IObservable: представляет наблюдаемый объект. Определяет три метода: AddObserver() (для добавления подписчика(наблюдателя)), RemoveObserver() (удаление набюдателя) и NotifyObservers()(уведомление наблюдателей)
  • ConcreteObservable: конкретная реализация интерфейса IObservable. Определяет коллекцию объектов наблюдателей.
  • IObserver: представляет наблюдателя, который подписывается на все уведомления наблюдаемого объекта. Определяет метод Update(), который вызывается наблюдаемым объектом для уведомления наблюдателя.
  • ConcreteObserver: конкретная реализация интерфейса IObserver
При этом наблюдаемому объекту не надо ничего знать о наблюдателе кроме того, что тот реализует метод Update(). С помощью отношения агрегации реализуется слабосвязанность обоих компонентов. Изменения в наблюдаемом объекте не виляют на наблюдателя и наоборот.В определенный момент наблюдатель может прекратить наблюдение. И после этого оба объекта - наблюдатель и наблюдаемый могут продолжать существовать в системе независимо друг от друга.КомандаКоманда — это поведенческий паттерн проектирования, который превращает запросы в объекты, позволяя передавать их как аргументы при вызове методов, ставить запросы в очередь, логировать их, а также поддерживать отмену операций......
т.к. В WindowsForms уже есть реализация обработчиков, то этот паттерн нам особо не понадобится, но я всё же оставлю ссылку на негоhttps://refactoring.guru/ru/design-patterns/command
побробная информация о паттернах :https://refactoring.guru/ru/design-patterns/
На этом я заканчиваю эту статью. Если она была вам полезна и поможет чем-нибудь, я буду очень рад.Не игнорируйте паттерны и архитектуры, они вас спасут!
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_proektirovanie_i_refaktoring (Проектирование и рефакторинг), #_c#, #_razrabotka_pod_windows (Разработка под Windows), #_s# (С#), #_note, #_vshe (вшэ), #_peerreview, #_arhitektury (архитектуры), #_patterny (паттерны), #_proektirovanie_i_refaktoring (
Проектирование и рефакторинг
)
, #_c#, #_razrabotka_pod_windows (
Разработка под Windows
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 25-Ноя 09:02
Часовой пояс: UTC + 5