Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
IML, MVD — что это?
<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>
Простите, но код ваш на ng ужасен
Вы не работаете с AngularJs
но позволяете себе сравнивать его
вдобавок, критиковать, основываясь только на поверхностном прочтении непонятных материалов.
Зачем?
А зачем вы вообще тогда решили написать эту статью, если не разбираетесь, простите?
Ваш код и подход ужасны
Некую кодогенерирующую штуку с полноценным js фреймворком…
Но если очень хочется, то напишите хотя бы TO DO List приложение на IM
что по перформенс
что по подходу организации UI =)
@(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 и любой другой продукт
написать хотя бы приблизительно похожие по функционалу приложения
Вопрос не в сложности, вопрос в том, что сравнивать нужно не маленькие кусочки кода, а сколько-нибудь рабочие корректно реализованные на обоих технологиях приложения.
Хорошо, пусть это не кодогенератор, хотя вопрос очень спорный (статью как работает ИМЛ читал, вопросы к пунктам 2, 5, 6, 7), это всё равно некая ненужная прослойка между сервером и клиентом.
Из всех статьей где сравнивают один инструмент с другим, то выделяют общий функционал и проводится аналогия. Согласитесь, объем текста, для реализации такой статьи будет большим.
Сайт, на который я дал ссылку, проводит отличное сравнение технологий.
Провести анализ технологии, коммьюнити, поддержки и многих прочих факторов.
п. 2 — нельзя же смотреть на мир только со своей колокольни. С точки зрения стандартизации веба (HTML/JS/CSS) это не совсем то, чего добиваются спецификации.
п. 5, 6, 7 — в Ангуляре парсер для обработки и создания шаблона(читайте как view в c#), причём написан на Js со всеми вытекающими.
А как с отладкой кода в IML?
там 176 человек делает коммиты, а я занимаюсь в свободное от работы время, тем что продвигаю инструмент, так что пока могу только так. Если будет интерес, могу реализовать To Do MVC.
Но вы опубликовали статью в блогах C#, Js, .Net, а не в блоге «Я пиарюсь», отсюда и получаете обратную связь на статью.
У меня ведь нет задачи завалить вас, но у меня чувство того, что AngularJs выставлен в плохом свете.
вам решать делать или нет, но мне кажется, что это вывело бы статью на более качественный уровень
вам решать делать или нет, но мне кажется, что это вывело бы статью на более качественный уровень
Меня дико удивлют попытки перенести фронтенд и фронтенд логику в бекенд.
Не нравится JS есть надмножество типа Typescript или же такие диалекты как Coffeescript и ему подобные
Конечно, куда лучше 2 программиста, один пишет Command на C#, другой вызывает её с JavaScript
Но для качества кода вариант с двумя программистами куда лучше, ведь каждый из них пользуется инструментом для своей части разработки и не трогает чужого.
Знаете ле вы, что с Angular можно использовать и языки шаблонов, например Jade?
Статья интересная в разрезе про IML, примеры с angural поясняют магию
сравнивать их не стоит, они слишком разные
Молотком и микроскопом можно вбить гвоздь, но каждый из них лучше применять в своей сфере.
Если вы специались по IML, велкам, расскажите нам о IML.
на IML специалист по IML.
Не надо придумывать абстрактных сравнений которые кроме вашего низкого профессионального уровня ничего не могут подтверить
Клевый фреймворк из 20 коммитов, 10 из которых «Update (Create) README.md»,
Я оцениваю профессионализм программиста по качеству кода (вот мой github.com/IncodingSoftware/Incoding-Framework ) а Вы как?
[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();
}
[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_<контекст>),
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));
}
Вы бы в качестве своего примера, показали тест на калькулятор, там ещё меньше кода будет.
Should be push — проверяет то, что будет выполнен Push, что не так то?
У Вас есть какие то проекты на github?
Тест должен быть читаемым. Если в нем много кода — значит, выносите код в именованные операции. У Мезароса все описано.
«Сперва добейся»?
Код теста должен быть полный (убрали половину строк) и равный по сложности. Покажите Ваш вариант для теста 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
Ни в коем случаи я не перехожу на личности, я хочу мнение о коде.
Смысл в обобщенном Repository
Ваш вариант AddGenreCommand принимает Genre, что крайне избыточно, потому что где то есть код, который заполняет AddGenreCommand, но зачем?
В it Вы проверяете, что Ваш Genre, который Вы создали сохранился, Вам не кажется что смысла в этом нет?
То есть тест покрывает просто факт вызова метода Add?
Разве у Вас есть много Command, где НЕ используется IRepository?
Fixture = new Fixture(); зачем усложнять, если можно обращается сразу к Fixture.Instance?/blockquote>
У Fixture нет Instance.
Где Unit of Work?
Это не важно. Операция Add репозитория атомарна.
Вопрос не имеет отношения к тесту.
Нет, не кажется. Это и есть задача теста.
Это не важно. Операция Add репозитория атомарна.
Нет, он покрывает факт вызова метода Add с правильными параметрами.
Это один из вариантов. Можно написать иначе, просто тогда инициализация теста будет многословнее.
Задам его отдельно, почему Repository<Genre>.Add вместо Repository.Add<Genre>()
Но она же бредовая, Вы плодите кучу кода, зачем усложнять, почему нельзя просто сделать Post COmmand, которую превратить в Genre (может в несколько entity).
Идея проверить правильность формирования Genre, а не то что Вы не забыли вызвать Add (хотя и это будет проверенно)
тест будет проверять, что Вы передали в Controller поля, который превратились в Genre, разве не проще зараз все проверить?
А разве плохо увидеть всю картину сразу?
Если в ней слишком много деталей — да плохо.
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);
}
Человек не способен все осознать за один прием
dispatcher.Push(composite =>
{
composite.Quote(step1);
composite.Quote(step2);
composite.Quote(step3);
});
Если делать, как Вы, то код создания Product выносится в слой выше, тем самым скрываете, то как строится объект.
Конечно, куда проще бегать по слоям, что бы понять, как это работает.
Вы хотели аргументов, тогда посчитайте кол-во действий и классов нужных для реализации Add Genre, к примеру у меня:
1. Add Genre Command Class ( и тест )
2. Url.Disaptcher().Push(new AddGenreCommand())
И все…
очень много повторяющихся паттернов, на которые вы пишете повторяющиеся тесты
Вы редко Save используйте?
Я его редко тестирую.
Repository.Save(new Genre(){ Name = Name, IsNew = StartDt > DateTime.Now })
AngularJS vs IML