Как стать автором
Обновить

Комментарии 68

IML, MVD — что это?

IMLincoding meta language
MVD — Model View Dispatcher, позволяет вызывать Command и Query без написания Controller на asp.net mvc.
Я так и не понял что вы пытаетесь сравнить. Некую кодогенерирующую штуку с полноценным js фреймворком…
У меня сложилось впечатление, что вы просто не умеете готовить Angular, ну или с# вам не даёт, или что там…
<div ng-controller="productController"> 
  <form name="AddForm">
    @Html.TextBoxFor(r => r.Name)
    @Html.CheckboxFor(r => r.IsGood) 
    <input type="submit" value="save"  ng-submit="submit" />
  </form>
</div>

зачем этот код? напишите нормальную html страницу и используйте c# как rest.

И вывод у вас не полный и сравнивать эти вещи не корректно. Но если очень хочется, то напишите хотя бы TO DO List приложение на IML, а потом сравните.
>У меня сложилось впечатление, что вы просто не умеете готовить Angular, ну или с# вам не даёт, или что там…

Автор сам дает ответ на этот вопрос: «Я не являюсь знатоком всех тонкостей angularJs, но прочитав 10 статьей обзора этого инструмента».

Т.е. он не только не умеет его готовить, он его в «руках не держал».
Простите, но код ваш на ng ужасен, особенно когда вы пытаетесь криво за счет jquery передать параметры в ajax запрос. По поводу интелисенс — есть webstorm, netbeans 8, vs+resharper(plugin for ng). Еще в древние времена когда вместо ASP.MVC были ASP web forms мне казалось это ужасно. Все что вы пытались так высветить в высшем свете на ng решается очень просто и лаконично красиво. Может по поводу шаблнов не очень, но никто не мешает использовать в директиве рендеринг в элемент за счет того же ReactJS, когда у вас очень много данных на странице…
Вы не работаете с AngularJs, но позволяете себе сравнивать его с чем-то, и, вдобавок, критиковать, основываясь только на поверхностном прочтении непонятных материалов. Зачем?
Вы не работаете с AngularJs

Мы решаем задачи другим способом и хотели об этом рассказать.

но позволяете себе сравнивать его

Я должен спросить разрешение?

вдобавок, критиковать, основываясь только на поверхностном прочтении непонятных материалов.

Что именно я критиковал? Материал был взят из очень известного блога и автор тоже популярный.

Зачем?

Затем, что бы на примере продемонстрировать возможности нашего инструмента, разве это было не очевидно?
Исчерпывающе.
А зачем вы вообще тогда решили написать эту статью, если не разбираетесь, простите?
А зачем вы вообще тогда решили написать эту статью, если не разбираетесь, простите?

А с чего Вы взяли, что я не разбираюсь? Или мне надо сделать десятки проектов на нем ( AngularJs ), что бы потом можно было его сравнивать?
Да, вы не разбираетесь и об этом вам выше сказал xGromMx. Ваш код и подход ужасны.
Ваш код и подход ужасны

Изучал по статьям из блога ( lostechies.com/gabrielschenker/2014/02/26/angular-js-blog-series-table-of-content/ ). Я виноват, что google выдает этот курс, как самый популярный? Я привел рабочие примеры кода на AngularjS, причем некоторые прямо из официальной документации.

Некую кодогенерирующую штуку с полноценным js фреймворком…

кодогенерации нету!

Но если очень хочется, то напишите хотя бы TO DO List приложение на IM

А как Вам browsio, он открыт на open source.
Так же на open source Inc Music Store ( аналог asp.net mvc music store )

По поводу «хотя бы», на Incoding Framework выполнены сотни проектов, например
И все что вы показали ужасно что по перформенс что по подходу организации UI =)
что по перформенс

Все проекты расположены на тестовом сервере. Вот пример на live сервере www.pazar3.mk/mk/Listing/Classified/Ads

что по подходу организации UI =)

Это не имеет ни какого отношения к IML или framework.
@(Html.When(JqueryBind.InitIncoding)
 .Do()
 .AjaxGet(Url.Action("Personal","Fetch"))
 .OnSuccess(dsl => dsl.Self().Core().Insert.WithTemplate(tmplId.ToId()).Html())
 .AsHtmlAttributes()
 .ToDiv())

Простите, а это по-вашему не генерация HTML/JS из того инструмента?

Мне всё равно на browserio и любой другой продукт. Если вы делаете сравнение, оно должно быть адекватным. Вы должны всесторонне изучить оба инструмента, написать хотя бы приблизительно похожие по функционалу приложения, чтобы потом сравнить реализации идентичной функциональности и архитектуру в целом.
Простите, а это по-вашему не генерация HTML/JS из того инструмента?

Нет. Вот, статья про то, как работает IML. Там целый раздел про «Ни кто ни чего не генерирует»

Мне всё равно на browserio и любой другой продукт

Я Вам не продукт показываю, а демонстрирую возможности IML.

написать хотя бы приблизительно похожие по функционалу приложения

То есть, вы считаете TO DO LIST это очень сложное приложение?
Объективная мысль:
Вопрос не в сложности, вопрос в том, что сравнивать нужно не маленькие кусочки кода, а сколько-нибудь рабочие корректно реализованные на обоих технологиях приложения.

Субъективная мысль:
Хорошо, пусть это не кодогенератор, хотя вопрос очень спорный (статью как работает ИМЛ читал, вопросы к пунктам 2, 5, 6, 7), это всё равно некая ненужная прослойка между сервером и клиентом.
Вопрос не в сложности, вопрос в том, что сравнивать нужно не маленькие кусочки кода, а сколько-нибудь рабочие корректно реализованные на обоих технологиях приложения.

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

Хорошо, пусть это не кодогенератор, хотя вопрос очень спорный (статью как работает ИМЛ читал, вопросы к пунктам 2, 5, 6, 7), это всё равно некая ненужная прослойка между сервером и клиентом.

2. — это нормальная практика для asp.net mvc ( TextBox, DropDown и т.д. )
5, 6, 7 — разве Angular не запускает свой parser?

Могу сказать один веский аргумент в сторону IML, кол-во JavaScript файлов уменьшается до 0 ( кроме файла framework 12Kb и jquery, а так же сторонних плагинов и template enginte, которые так же надо подключать для Angular ), потому что не надо реализовывать логику, надо просто её описать ( декларативность имеет свои плюсы )
п. 2 — нельзя же смотреть на мир только со своей колокольни. С точки зрения стандартизации веба (HTML/JS/CSS) это не совсем то, чего добиваются спецификации.
п. 5, 6, 7 — в Ангуляре парсер для обработки и создания шаблона(читайте как view в c#), причём написан на Js со всеми вытекающими. А как с отладкой кода в IML?

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

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

Я рассматриваю ситуацию со следующей точки зрения:
Завтра ко мне приходит новый проект и говорят, выбирай технологию — IML или Angular. И так как я не шалтай-болтай, мне нужно доказать, почему я её выбрал, и не просто потому, что Js я знаю лучше чем IML. Провести анализ технологии, коммьюнити, поддержки и многих прочих факторов. Я открываю эту статью, чтобы она помогла мне провести анализ с технической точки зрения, трачу пару часов на то, чтобы вникнуть в неё и понимаю, что последние пару часов я провёл зря.
Сайт, на который я дал ссылку, проводит отличное сравнение технологий
.
там 176 человек делает коммиты, а я занимаюсь в свободное от работы время, тем что продвигаю инструмент, так что пока могу только так. Если будет интерес, могу реализовать To Do MVC.

Провести анализ технологии, коммьюнити, поддержки и многих прочих факторов.

Конечно сравнивать Angular ( миллионы пользователей, десятки разработчиков и т.д. ) и нас крайне сложно, но с другой стороны если ничего не делать, то так все и останется.

п. 2 — нельзя же смотреть на мир только со своей колокольни. С точки зрения стандартизации веба (HTML/JS/CSS) это не совсем то, чего добиваются спецификации.

Разрабатываю я приложения на asp.net mvc и для заказчиков, а не для стандартов веба.

п. 5, 6, 7 — в Ангуляре парсер для обработки и создания шаблона(читайте как view в c#), причём написан на Js со всеми вытекающими.

И в IML написан на JS

А как с отладкой кода в IML?

Отладчик в разработке. Вопрос на самом деле каверзный, но мы работает над этим. В рамках компании, хватает того, что разработчик framework все о нем знает и всегда поможет, если что не работает, но конечно планируем покрыть этот момент.

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

P.S. Мы выполняем проекты любой сложности на incoding framework.
Я верю, что вы делаете качественные приложения для своих заказчиков.

Но вы опубликовали статью в блогах C#, Js, .Net, а не в блоге «Я пиарюсь», отсюда и получаете обратную связь на статью. У меня ведь нет задачи завалить вас, но у меня чувство того, что AngularJs выставлен в плохом свете.

там 176 человек делает коммиты, а я занимаюсь в свободное от работы время, тем что продвигаю инструмент, так что пока могу только так. Если будет интерес, могу реализовать To Do MVC.

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

Я думал в какой лучше, но склонился к этим, может это не правильно. Я на хабре не давно.

У меня ведь нет задачи завалить вас, но у меня чувство того, что AngularJs выставлен в плохом свете.

Я указал те моменты, в которых я считаю, что мы лучше, если есть контр-аргументы то давайте обсудим. Пока в обсуждениях чаще идет упор на «КАК ОН ПОСМЕЛ УПОМИНАТЬ AngularJs».

вам решать делать или нет, но мне кажется, что это вывело бы статью на более качественный уровень

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

решил сделать, подробности тут
Вы молодец. Теперь, когда у вас есть эталонные реализации TODO на обоих технологиях, этот пост мог бы быть написан намного объективнее. Жаль что так вышло не с самого начала.
Меня дико удивлют попытки перенести фронтенд и фронтенд логику в бекенд. Это что типа такая мода теперь? JS очень гибкий и мощный, имеет огромное колличество модулей, фреймворков и прочего. Не нравится JS есть надмножество типа Typescript или же такие диалекты как Coffeescript и ему подобные. C# прекрасный язык, но для бекенда, всему своя задача.
Меня дико удивлют попытки перенести фронтенд и фронтенд логику в бекенд.

Конечно, куда лучше 2 программиста, один пишет Command на C#, другой вызывает её с JavaScript

Не нравится JS есть надмножество типа Typescript или же такие диалекты как Coffeescript и ему подобные

IML это декларативный язык, он в отличии от тех, что Вы привели выше имеет функциональную часть, которую можно быстро оценить на видео уделив 10 минут
Мне кажется, вы сравниваете совершенно разные вещи и при этом код для AngularJS не слишком хорош (уже расписали выше). По поводу кода IML не могу ничего сказать.

Конечно, куда лучше 2 программиста, один пишет Command на C#, другой вызывает её с JavaScript

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

Когда работают 2 человека, то появляются проблемы:
1. Кто то, работает быстрее.
2. Не понятно, кто ошибся, потому что каждый считает, что его код рабочий.

Разве плохо, когда один отвечает за проделанную работу?
Зависит от размера проекта.
Я не буду спорить на эту тему. В обоих случаях есть и плюсы и минусы. В сети достаточно материала :)
Сравниваете язык шаблонов с ванильным HTML, пусть и в связке с Angular?
Знаете ле вы, что с Angular можно использовать и языки шаблонов, например Jade?
Знаете ле вы, что с Angular можно использовать и языки шаблонов, например Jade?

IML поддерживает любой движок для template ( подробней ) и позволяет их менять. Cache работает на основе local storage, что позволяет хранить его между сессиями. А вот может ли AngularJs For(r=>r.PropertyFromMyServerModel)?
Во блин флейма развели, это же дотнет, у них всегда свои велосипеды через попу реализованы и они их считают самыми лучшими. Вы что думаете, тут будет какое-то исключение?
Какая разница, на чем server-side?
Да никакой, причем тут серверная сторона?
Тут же просто очередной велосипед с квадратными колесами.
Устал, что из статьи в статью носится jquery стиль работы с моделями, хотя там мощная работа с ресурсами, с кешированием и прочими свистелками.
docs.angularjs.org/tutorial/step_11
docs.angularjs.org/api/ngResource/service/$resource

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

Это основная цель, я же не руководство по AngularJs делаю.

сравнивать их не стоит, они слишком разные

Angular получает Json через Ajax, что бы потом переделать его в Html и IML делает тоже самое. Это мое мнение, но если взять любое веб приложение, то задачи одинаковые.

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

Мне кажется любой framework направлен на увлечение продуктивности труда ( только после его изучения ), так что сфера у нас одна.

json это далеко не ресурс, который поддерживает rest $save, $delete и т.д., умеет работать с кешем, знает о DI, легко тестируется, легко расширяется.

точно так же вы привели пример с шаблонами, где явно в цикле прогоняете данные и вставляете в шаблон, а в ангуляре же используется биндинг и данные сами обновляются при изменени во всех шаблонах. Разница огромная. То что вы будете делать руками, ангуляр сделает сам и вам не нужно следить за целостностью и синхронизацией шаблонов.
Ужасно не профессиональное сравнение, убогий материал, убогие примеры на обоих языках.
Не профессионализм автора на лицо!
Если вы специались по IML, велкам, расскажите нам о IML. Не надо придумывать абстрактных сравнений которые кроме вашего низкого профессионального уровня ничего не могут подтверить. Ибо для сравненияя надо гратно определить критерии, а тут это сделано в корне не правильно.
Для сравнения надо было написать тогда уж приложение взятое из реальной жизни, причем на ангуляре должен писать специалист по ангулару а на IML специалист по IML.
Имхо также сравнение этих инструменитов не корректно по сути, ибо js разработчики врятли найдут хоть 1 аргумент за то чтобы начать писать на IML, также имхо специалисту по C# может оказаться проще работать на IML.
Другое дело сравнивать Backbone и Angular — две равные технологии где разработчики легко могут сменить одну на другую.

Если вы специались по IML, велкам, расскажите нам о IML.

Уже рассказывал habrahabr.ru/post/209734/

на IML специалист по IML.

Я автор Incoding framework

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

Я оцениваю профессионализм программиста по качеству кода (вот мой github.com/IncodingSoftware/Incoding-Framework ) а Вы как?

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

P.S. Понятно, что статья провалилась, но я постараюсь исправится реализовав To Do MVC на IML и описав этот процесс в следующих статьях.

> Я автор Incoding framework
Это все объясняет, но AngularJS это детище Google.

>(вот мой github.com/IncodingSoftware/Incoding-Framework ) а Вы как?

Клевый фреймворк из 20 коммитов, 10 из которых «Update (Create) README.md»,
Я оцениваю профессионализм программиста по качеству кода (вот мой github.com/IncodingSoftware/Incoding-Framework ) а Вы как?

И мы тоже.

Тесты вида «When_default_dispatcher_push_throw_with_mute_event_by_attributes» очень много говорят о профессионализме программиста.
А чем плохо название?
Тем, что из него не понятно, что тестируется. Ни базовые условия (Arrange), ни действие (Act), ни проверка (Assert).
Это BDD (почитайте про MSpec), если Вам не понятно, то это ничего не значит.
Во-первых, это не BDD, а поведенческое тестирование. Во-вторых, если человеку, который читает тест, не понятно, что тест делает, это плохо говорит о тестах (потому что одна из задач тестов — фиксация и демонстрация поведения).

Для MSpec читаемость достигается правильным именованием It (should_<описание проверки>; should_be_push — это не понятно, что такое (возможно, вы просто плохо знаете английский), и читаемым контекстом (зафиксированным в названии теста, When_<контекст>),

Из чтения теста
[Subject("Authentication")]
public class When_authenticating_an_admin_user
{
    Establish context = () => {Subject = new SecurityService(foo, bar);};

    Because of = () => Token = Subject.Authenticate("username", "password");

    It should_indicate_the_users_role = () => Token.Role.ShouldEqual(Roles.Admin);
    It should_have_a_unique_session_id = () => Token.SessionId.ShouldNotBeNull();
}

понятно, что при аутентификации администратора у него должна быть роль и id сессии.

При чтении теста
    [Subject(typeof(MessageBase<>))]
    public class When_message_base_push
    {
        #region Fake classes

        class FakeCommand : CommandBase
        {
            public override void Execute()
            {
                throw new NotImplementedException();
            }
        }

        class FakeMessage : MessageBase<string>
        {
            public override void Execute()
            {
                Dispatcher.Push(new FakeCommand(), setting => setting.Delay = delaySetting);
            }
        }

        #endregion

        #region Establish value

        static FakeMessage message;

        static Mock<IDispatcher> dispatcher;

        static MessageDelaySetting delaySetting;

        #endregion

        Establish establish = () =>
                                  {
                                      delaySetting = Pleasure.Generator.Invent<MessageDelaySetting>();
                                      var unitOfWork = Pleasure.MockAsObject<IUnitOfWork>(mock => mock.Setup(r => r.IsOpen()).Returns(true));
                                      message = Pleasure.Generator.Invent<FakeMessage>(dsl => dsl.GenerateTo(r => r.Setting, inventFactoryDsl => inventFactoryDsl.Tuning(r => r.UnitOfWork, unitOfWork)));
                                      dispatcher = Pleasure.Mock<IDispatcher>();
                                      IoCFactory.Instance.StubTryResolve(dispatcher.Object);
                                  };

        Because of = () => message.Execute();

        It should_be_push = () => dispatcher.ShouldBePush(new FakeCommand(), new MessageExecuteSetting
                                                                                 {
                                                                                         UnitOfWork = message.Setting.UnitOfWork, 
                                                                                         Delay = delaySetting
                                                                                 });
    }

не понятно, что имеется в виду.
Во-первых, это не BDD, а поведенческое тестирование. Во-вторых, если человеку, который читает тест, не понятно, что тест делает, это плохо говорит о тестах (потому что одна из задач тестов — фиксация и демонстрация поведения).

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

Для MSpec читаемость достигается правильным именованием It (should_<описание проверки>; should_be_push — это не понятно, что такое (возможно, вы просто плохо знаете английский), и читаемым контекстом (зафиксированным в названии теста, When_<контекст>),


Should be push — проверяет то, что будет выполнен Push, что не так то?

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

[
    public class When_add_genre
    {
        static MockMessage<AddGenreCommand, object> mock;

        Establish establish = () =>
                                  {
                                      var command = Pleasure.Generator.Invent<AddGenreCommand>();

                                      mockCommand = MockCommand<AddGenreCommand>
                                              .When(command);
                                  };

        Because of = () => mock.Original.Execute();

       It should_be_save = () => mock.ShouldBeSave<Genre>(genre => genre.ShouldEqualWeak(mock.Original));
    }


У Вас есть какие то проекты на github?
Вы бы в качестве своего примера, показали тест на калькулятор, там ещё меньше кода будет.

Тест должен быть читаемым. Если в нем много кода — значит, выносите код в именованные операции. У Мезароса все описано.

Should be push — проверяет то, что будет выполнен Push, что не так то?

Все не так. Проверка на то, что выполнен push — это BePushed, WasPushed или PushCalled.

У Вас есть какие то проекты на github?

"Сперва добейся"?
Тест должен быть читаемым. Если в нем много кода — значит, выносите код в именованные операции. У Мезароса все описано.

Код теста должен быть полный (убрали половину строк) и равный по сложности. Покажите Ваш вариант для теста AddGenreCommand с учетом всех Ваших слоев и сравним тогда объективно.

«Сперва добейся»?

Ну Вы же критикуете, так давайте уравняем шансы, что бы я тоже составил о Вас мнение.
Код теста должен быть полный (убрали половину строк) и равный по сложности. Покажите Ваш вариант для теста AddGenreCommand с учетом всех Ваших слоев и сравним тогда объективно.

А при чем тут слои? А пример читаемого кода — вот (только надо отметить, что (а) и ваш вариант был вполне читаемым и (б) я не правлю ваши архитектурные проблемы):

public class When_add_genre
    {
        static Fixture Fixture;
        static Genre ExpectedGenre;
        static Mock<IRepository<Genre>> Repository;
        static AddGenreCommand Target;

        Establish context = () =>
                                  {
                                      Fixture = new Fixture();
                                      ExpectedGenre = Fixture.Create<Genre>();
                                      Repository = new Mock<IRepository<Genre>>();
                                      Target = AddGenreCommand(Repository.Object){Genre = ExpectedGenre};
                                  };

        Because of = () => Target.Execute();

        It should_be_added_to_repository = () => Repository.Verify(r => r.Add(It.Is<Genre>(actual => actual.ShouldBeEquivalent(ExpectedGenre))));
    }


Ну Вы же критикуете, так давайте уравняем шансы, что бы я тоже составил о Вас мнение.

Обсуждать надо приводимые аргументы, а не личность оппонента.
Обсуждать надо приводимые аргументы, а не личность оппонента.

Ни в коем случаи я не перехожу на личности, я хочу мнение о коде.

When_add_genre

Давайте пройдем по Вашему варианту:
1. Смысл в обобщенном Repository
примечание: уже проходили такое, в сто раз меньше кода при использовании обобщенных МЕТОДОВ Repository
2.Ваш вариант AddGenreCommand принимает Genre, что крайне избыточно, потому что где то есть код, который заполняет AddGenreCommand, но зачем? Чем плох вариант составить Genre из полей Command (удобно для asp.net mvc binding)?
3. В it Вы проверяете, что Ваш Genre, который Вы создали сохранился, Вам не кажется что смысла в этом нет? То есть тест покрывает просто факт вызова метода Add?
примечание: мой пример, сравнивает поля AddGenreCommand с новым Genre, тем самым проверяем правильность преобразования
4. Разве у Вас есть много Command, где НЕ используется IRepository? Зачем копировать одни и те же строки.
5. Fixture = new Fixture(); зачем усложнять, если можно обращается сразу к Fixture.Instance?
6. Где Unit of Work? Скорей всего он во внешнем слое, который в этом тесте не показан, что говорит о наличии ещё одного теста, но зачем не понятно.

P.S. Вы показали мне пример, того как я писал раньше, потому что мы так же использовали слои, но теперь я пишу в разы быстрее из-за меньшего количества кода нужного для решения задачи.

Ни в коем случаи я не перехожу на личности, я хочу мнение о коде.

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

Смысл в обобщенном Repository

Вопрос не имеет отношения к тесту.

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

Это один из вариантов. Можно написать иначе, просто тогда инициализация теста будет многословнее.

В it Вы проверяете, что Ваш Genre, который Вы создали сохранился, Вам не кажется что смысла в этом нет?

Нет, не кажется. Это и есть задача теста.

То есть тест покрывает просто факт вызова метода Add?

Нет, он покрывает факт вызова метода Add с правильными параметрами.

Разве у Вас есть много Command, где НЕ используется IRepository?

Понятия не имею. Я показываю тест конкретной команды.

Fixture = new Fixture(); зачем усложнять, если можно обращается сразу к Fixture.Instance?/blockquote>
У Fixture нет Instance.

Где Unit of Work?

Это не важно. Операция Add репозитория атомарна.
Вопрос не имеет отношения к тесту.

Задам его отдельно, почему Repository<Genre>.Add вместо Repository.Add<Genre>(). На своем опыте скажу, что писать IGenreRepository, крайне утомительно, когда у Вас сотни entity.

Нет, не кажется. Это и есть задача теста.

Но она же бредовая, Вы плодите кучу кода, зачем усложнять, почему нельзя просто сделать Post COmmand, которую превратить в Genre (может в несколько entity).

Это не важно. Операция Add репозитория атомарна.

Атомарно должна быть задача Add Genre, а не метод из Вашего ядра инфраструктуру, его то зачем проверять, каждый раз? Идея проверить правильность формирования Genre, а не то что Вы не забыли вызвать Add (хотя и это будет проверенно)

Нет, он покрывает факт вызова метода Add с правильными параметрами.

Вы создали объект и передали его в Command и потом проверили, что это объект сохранился, а Выше тест будет проверять, что Вы передали в Controller поля, который превратились в Genre, разве не проще зараз все проверить?

Это один из вариантов. Можно написать иначе, просто тогда инициализация теста будет многословнее.

А разве плохо увидеть всю картину сразу?
Задам его отдельно, почему Repository<Genre>.Add вместо Repository.Add<Genre>()

Не Repository, а IRepository, класс при этом может быть и один. Удобно это тогда, когда разные аггрегаты лежат в разных хранилищах.

Но она же бредовая, Вы плодите кучу кода, зачем усложнять, почему нельзя просто сделать Post COmmand, которую превратить в Genre (может в несколько entity).

Не понимаю, о чем вы говорите. Задача теста в том, чтобы протестировать, что команда корректно выполняется (мы сейчас не рассматриваем тот факт, что делать это дожен обработчик). Выполнение команды — это создание соответствующего аггрегата в репозитории. Это и тестируется.

Идея проверить правильность формирования Genre, а не то что Вы не забыли вызвать Add (хотя и это будет проверенно)

Проверяется и то, и другое.

тест будет проверять, что Вы передали в Controller поля, который превратились в Genre, разве не проще зараз все проверить?

Тестирование контроллера, равно как и сквозное тестирование — это отдельная задача. Здесь тест покрывает конкретную команду (кстати, именно поэтому поведенческое тестирование там лишнее, обычный юнит-тест справился бы ничем не хуже).

А разве плохо увидеть всю картину сразу?

Если в ней слишком много деталей — да плохо. Человек не способен все осознать за один прием.
Если в ней слишком много деталей — да плохо.

Приведу пример AddStoreCommand
public override void Execute()
        {
     var store = Repository.GetById<Store>(StoreId);
     var product = new Product
                              {
                      Name = Name, 
                      Description = Description, 
                      Price = Price, 
                      Asin = Asin, 
                      Author = Author, 
                      Image = Image.ReturnOrDefault(r => new HttpMemoryPostedFile(r).ContentAsBytes, new byte[0])
                              };
      store.AddProduct(product);
        }

Если делать, как Вы, то код создания Product выносится в слой выше, тем самым скрываете, то как строится объект.

Человек не способен все осознать за один прием

Конечно, куда проще бегать по слоям, что бы понять, как это работает.

P.S. Ваш подход построен на рутином написании слоев и тестов к ним, хотя все это можно агрегировать в одну Command.
На вопрос о том, что делать когда код разрастётся, то для этих целей есть Composite, который может разделять сложные задачи на части и потом в рамках ОДНОЙ транзакции выполнять.
dispatcher.Push(composite =>
                        {
                            composite.Quote(step1);
                            composite.Quote(step2);
                            composite.Quote(step3);
                        });


Вы хотели аргументов, тогда посчитайте кол-во действий и классов нужных для реализации Add Genre, к примеру у меня:
1. Add Genre Command Class ( и тест )
2. Url.Disaptcher().Push(new AddGenreCommand())
И все…

Если делать, как Вы, то код создания Product выносится в слой выше, тем самым скрываете, то как строится объект.

Я уже говорил, что это только один из возможных вариантов. Можно ведь и модел-биндером собирать сущность сразу, тогда этого кода не будет вообще.

Конечно, куда проще бегать по слоям, что бы понять, как это работает.

А зачем? При правильной декомпозиции задачи вся существенная информация находится в одном месте.

Вы хотели аргументов, тогда посчитайте кол-во действий и классов нужных для реализации Add Genre, к примеру у меня:
1. Add Genre Command Class ( и тест )
2. Url.Disaptcher().Push(new AddGenreCommand())
И все…

Эти аргументы не имеют никакого отношения к читаемости теста, который мы обсуждаем в этой ветке.
Мои wrapper, позволяют описывать тест с помощью языка.
Скажем у Вас в коде Command/Query есть Repository.GetById(ArtistId), то в тесте mockQuery.StubGetById(command.ArtistId, artist).

P.S. Имея единый стандарт для кода, можно построить под него и тесты (я к примеру использую R# live template для формирования разметки под тест)

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

Вы редко GetById используйте?
Вы редко Save используйте?
Вы редко любой другой метод из Repository?

Весь код очень похож, поэтому мы укоротили конструкции обернув их в Wrapper, а так же выделили общую инфраструктуру в incoding framework и теперь используем для всех проектов. В рамках Incoding Framework вся уникальная бизнес логика сконцентрирована в Command/Query, а Repository и Disaptcher это периферия, которая одинакова для всех

Вы редко Save используйте?

Я его редко тестирую. Я не вижу смысла писать враппер для конструкции, которая тестируется один раз.
Я его редко тестирую.

Вы редко используете Save? или Вы тестируете не все?
Поскольку это типовая операция над аггрегатом, она тестируется один раз, и проверяется, что аггрегат корректно ходит в/из хранилище. А при тестировании бизнеса проверяется, что корректно изменяется состояние аггрегата.
Хорошо, вот пример
Repository.Save(new Genre(){ Name = Name, IsNew = StartDt > DateTime.Now }) 

Вы будете его тестировать?
Это пример чего? Конкретной строчки кода? Тестируется обычно сценарий.

А вообще, зависит от конкретной реализации. Обычно выделяется одна точка, где перехватывается обращение в БД, и из нее достается аггрегат, состояние которого нужно проверять. Не видя структуры вашего репозитория, я не могу сказать, какая это точка.
Кстати о Вашем примере, а зачем вы убрали, то как настраивается foo, bar и объявления переменной Subject?
Мой код примера Вы выложили полностью же.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории