Път за отделяне на слоя изглед от съществуващо приложение winforms?

дадени:

  1. Нашата организация има стандартно приложение за windows form
  2. Формата и бизнес логиката са преплетени -- т.е. автономния изглед . Знаем, че моделът Autonomous View затруднява писането на модулни тестове. Целта е да вземем единична форма и да отделим логиката на представяне от самата форма, така че да имаме самостоятелен субект/обект на домейн, срещу който по-лесно могат да бъдат написани единични тестове.
  3. Ние НЕ правим пълно пренаписване. Разглеждам постепенен подход, който позволява един екран да се разглежда изолирано.
  4. След известно проучване смятам, че моделът модел за представяне или MVVM моделът е най-подходящ за начина, по който тази организация прави нещата.
  5. Тази организация обикновено предпочита по-малко нива на индиректност, поради което по-простото (макар и по-малко стабилно) е по-добро.
  6. Преходът от това, което е било към това, което ще бъде, трябва да бъде формулиран (лесно за преподаване на всеки разработчик, който вече е запознат с вътрешни концепции). Ето защо те искат да се придържат към Windows формуляри пред други по-нови технологии като WPF.
  7. Моделът на домейна няма да знае нищо за изгледа (формуляра). Формата ще бъде напълно наясно с промените в модела на домейна. Това прави 2 слоя индиректност. Още 1 би било добре (ето защо бих позволил MVVM).

Повечето от примерите за MVVM, които открих, илюстрират как се вписва заедно с WPF, а не с обикновени стари форми на Windows.

Два въпроса:

Имайки предвид всичко това, има ли нещо, което казах, което ви кара да мислите, че не съм на добър път или че съм на грешен път? Искам да направя някои препоръки към ръководството.

И накрая, знаете ли за добър пример за онлайн код, който би ми помогнал да създам прототип?


person Mario    schedule 16.05.2013    source източник
comment
winforms не поддържа MVVM. MVVM всъщност е създаден специално ЗА WPF, до голяма степен въз основа на Модел за представяне на Мартин Фаулър   -  person Federico Berasategui    schedule 17.05.2013
comment
Ако очаквате winforms да поддържат MVVM, ще ви е необходима рамка, базирана на winforms с поддръжка на неща като (реално) DataBinding, DataTemplates, DataTriggers и така нататък. Без тези концепции MVVM не може да съществува. Няма такава рамка, така че ще трябва да я създадете сами. Това е огромно усилие, което няма смисъл по никакъв начин. Това е като създаване на Windows UI рамка за QBasic.   -  person Federico Berasategui    schedule 17.05.2013
comment
Благодаря HighCore. Сигурен съм, че има хибрид (или алтернативен подход), който прави нещо като това, което питам (дори ако WPF е естественият спътник на MVVM). Интересувам се от мнения от всеки, който също е мислил да пресече този мост.   -  person Mario    schedule 17.05.2013
comment
Моделът MVP ще бъде по-подходящ за вашите изисквания и може да се прилага постепенно.   -  person Big Daddy    schedule 17.05.2013


Отговори (4)


Може би най-доброто, което можете да направите, е да погледнете кодовата си база с поглед към принципа на единична отговорност . Една от основните причини, че автономният изглед (и winforms, който го насърчава) е толкова труден за тестване, е, че разработчиците са склонни да събират всичко заедно в манипулатор на събития.

Задайте този въпрос на SO - https://stackoverflow.com/questions/16599778/asp-net-mvc3-linq-make-multiple-related-rows-fields-in-a-1-to-many-relationshi, става въпрос за MVC3, но е пълна бъркотия - един метод, който е отговорен за конфигурирането на gridview, конфигурирането на отговора и извличането на данните за попълване на gridview. Трудно е дори да знаеш откъде да започнеш да отговаряш на въпроса, камо ли да напишеш някакви разумни (да се четат: кратки и бързи за изпълнение) тестове, за да се гарантира, че решението работи.

Ако можете внимателно да прегледате кода си и внимателно да капсулирате цялата бизнес логика и/или интеграционни точки в услуги/компоненти/интерфейси (и реализации), за предпочитане в отделни асембли отвън.

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

След като сте написали и тествали всички тези различни проекти и сборки, вие ги въвеждате обратно в приложението си, като използвате инверсия на контрол (форма на инжектиране на зависимост). Това допълнително отделя потребителския ви интерфейс от различните бизнес логики, които вашето приложение трябва да изпълнява. Мечтата тук е, че ще стигнете до място, където, когато сте готови да пренапишете потребителския интерфейс, можете да използвате повторно компонентите на бизнес логиката, които вече са написани и тествани.

Мисля, че класът winform ще има конструктор, който приема много аргументи (комбинация от различните услуги, обсъдени по-горе). DI рамката ще отговаря за предоставянето на услугите на класа winform. След това в идеалния случай вашите манипулатори на събития winforms ще бъдат сравнително малки, просто извикващи сервизни методи със стойности на параметри, събрани от различните полета на формуляра.

Ето публикация за използването на Castle Windsor (рамка за инжектиране на зависимости ) с winforms: Използване на Castle.Windsor с приложения на Windows Forms. Има много различни DI рамки, използвам Castle Windsor, защото това е тази, която научих първи, всички те правят по същество едно и също нещо, така че всичко, което трябва да направите, е да намерите тази, която ви харесва.

Ето урок за разделяне на проблеми, което е базирано на уеб приложение, но трябва да бъде поучително как да се идентифицират и преработят услуги от съществуващо приложение за „кухненска мивка“.

Този отговор се превръща в книга и всичко е много абстрактно. Основното нещо е, че трябва да мислите за приложението като набор от лего блокове, които комбинирате, за да създадете функционалност (всеки блок е проблем), а потребителският интерфейс е просто лепилото, което държи блоковете заедно (тази аналогия не е перфектна) .

Наистина, това е повече изкуство, отколкото наука, но можете да тренирате ума си да гледа на проблемите по този начин и след като го направите, програмирането като цяло става много по-лесно. Завоят е малко стръмен, но продължавайте и ще стигнете.

person Jason    schedule 17.05.2013
comment
Благодарим ви, че отделихте време да предложите прозрението си. Сигурен съм, че нашият екип тук (включително и аз) би могъл да разработи подход за извличане на бизнес логиката в нейния собствен слой. Основното нещо, което питах, беше да избегна преоткриването, ако има здрави принципи, които да се извлекат от някакъв подход, който вече е изпробван и полиран. Във всеки случай точките ви са добре взети. Благодаря ти. - person Mario; 17.05.2013

В WPF можем да направим DataBinding между обектите в изгледа и съдържанието в ViewModel и поради това MVVM е идеалният модел за WPF.

Научих MVVM от този пример: http://www.scottlogic.co.uk/blog/colin/2011/05/a-simple-windows-phone-7-mvvm-tombstoning-example/

Това е урок за Windows Phone, но ако можете да разберете как работи, можете лесно да го използвате с всяко WPF приложение.

person cap7    schedule 17.05.2013

Мисля, че най-добрият ви вариант е да поставите ElementHosts< /a> във вашето съществуващо приложение winforms и поставете WPF съдържание вътре в тях. След това можете да използвате WPF и MVVM и постепенно да надстроите вашето приложение winforms до WPF.

Дори ако използвате някаква помощна рамка в winforms, винаги ще срещате ограничения, които ще доведат до мръсни, хакерски решения, които замърсяват чистотата, която се опитвате да постигнете.

Например, в winforms няма нищо, което да може да осигури същата функционалност като WPF ItemsControl с DataTemplates. Разгледайте този пример за ListBox с малко DataTemplates в WPF. Няма начин да постигнете нещо подобно в winforms с ListBox, без значение колко рамки на трети страни включвате.

В крайна сметка: поставете ElementHosts с WPF съдържание във всеки формуляр и можете постепенно да изчистите цялата бъркотия от winforms в чист, MVVM, тестван, независим от резолюцията, просто красив WPF UI. Настоявам (и никой все още не е успял да ми докаже, че греша), че това е единственият начин да извлечете нещо прилично от winforms.

person Federico Berasategui    schedule 17.05.2013
comment

Пиша голям код, където трябва да напиша много структури и след това да използвам void указатели към променливи на тези структури, например:

typedef struct {
    int age;
    double height;
}human_t;

и след това ще декларирам и инициализирам променлива от тип:"human_t"

human_t peter = {
    21,
    1.95 };

тогава ще направя празен указател към петър:

void* ptr = &peter;

това, от което се нуждая по-късно, е да знам, че "ptr" е указател към променлива от тип "human_t". Как мога да направя това? има ли някакъв вид предварително дефиниран метод в C? съжалявам за невежеството ми :) все още съм начинаещ .

- person Mario; 17.05.2013

Мразя да отговарям на въпроса си сам, но допълнителни изследвания и експерименти донякъде осветиха нещата.

Идеалното решение би било такова, при което извличането на обект на домейн би било само по себе си много подобно на практиките за проектиране, използвани в организацията. По същество това би било извличане на визуална форма в цялата й слава на потребителския интерфейс към по-абстрактна форма („VM“ или изглед-модел), която въплъщава концепциите, използвани във формулярите (комбота, бутони и т.н.) без използвайки действителни потребителски контроли. Тогава виртуалната машина ще бъде обвързана с изгледа, където всъщност се намират контролите.

За съжаление, това е трудно усилие, при което абстракциите трябва да са достатъчно здрави, за да се държат по подобен начин с контролите, към които се присвояват. Тъй като нашата организация има десетки и десетки персонализирани контроли, това не е кратък ред.

Вземете например обикновена вътрешна комбинирана кутия. Комбото представлява вход с ограничен набор от опции за избор. Нашият модел на данни е набор от данни в паметта. Комбинацията се свързва с определена таблица и докато потребителят попълва формуляра и по този начин предоставя критерии, неговите допустими селекции се филтрират допълнително. Тази комбинация показва стойност на потребителя (DisplayMember) и запазва друга в DB (ValueMember). Вероятно има малко повече от това; обаче, абстракцията на "поле" за комбо трябва да отчете някои от тези концепции, така че в крайна сметка да може да бъде правилно картографирана към изгледа. Освен това нашият формуляр се абонира за множество събития, произтичащи от неговите контроли. Те трябва да бъдат картографирани по някакъв начин. Така че ми се струва, че голяма част от функционалността на формата (изглед) трябва да има аналог във VM. По този начин VM става до известна степен сянка на физическата форма, която представлява.

Първоначално мислех, че може да е възможно да се извлече много обща абстракция на форма и нейните съставни контроли и след това да се картографира тази абстракция (която много наподобява оригиналната форма) към изгледа. Въпреки че може да е възможно, сега вярвам, че е непрактично и може само по себе си да създаде широк набор от нови проблеми.

Така че, докато исках да избегна провеждането на тестове срещу действителен екземпляр на формуляр, мисля, че това може да е по-добре, отколкото да се опитвам да добавя слой абстракция. Изграждането на тази абстракция би било подобно на усилията за пренаписване на нашите екрани, използвайки друга парадигма и по този начин да не се запази нищо от оригиналната форма на екрана. Тоест, дори когато можем да пренапишем една форма наведнъж, позволявайки постепенен преход, окончателната версия няма да използва повторно толкова много от оригиналната структура, колкото бихме се надявали.

person Mario    schedule 17.05.2013