Я написал небольшую, но полезную библиотечку для любителей TypeScript и ASP.NET MVC. Очень хотелось бы про нее рассказать — возможно какому-то разработчику на вышеупомянутой комбинации технологий (а возможно и целой команде) она существенно облегчит жизнь. Писать полноценную документацию на английском пока что времени нет.
К ней вообще нужно подходить осмысленно, с чувством, толком и расстановкой. Поэтому я решил написать статью на Хабрахабр, и вот прямо сейчас, под катом, я сделаю краткий обзор и покажу какую магию можно делать этой штукой. Добро пожаловать.
Лирическое введение
Вообще, меня давно и прочно будоражит идея тесной интеграции Back-End и Front-End на .NET стеке, что в свою очередь даже вылилось в попытку с наскоку написать целый транслятор из C# в JavaScript. Не скажу, что никаких результатов не было достигнуто — мой транслятор успешно перевел в JavaScript несколько C#-классов и в конечном итоге ушел в анабиоз и переосмысление архитектуры. Когда-нибудь я к нему еще вернусь. Обязательно.
настоящий геймерский тайпинг
Но, тем не менее, текущие задачи в проектах надо было как-то решать. А текущие задачи в почти любом web-проекте, в целом, достаточно типичны и, не побоюсь этого слова, скучны.
Вот сейчас я, с вашего позволения, абстрагируюсь от всяких сложных, но давно понятных материй, вроде использования Automapper, собирания IoC-контейнера и шуршания в БД посредством EF/NH/чего-нибудь, и переключусь ближе к фронтенду. Так вот — на стыке бекенда и фронтенда тоже много скучных и типичных задач (sarcasm). А конкретно — запросы к серверу на предмет JSON с данными, их отображение и выполнение всяких-разных операций AJAX-ом. Reinforced.Typings (а именно так я назвал свою маленькую помогалку) принесет в это царство уныния толику веселья, упрощение типичных задач, избавление от шаблонного кода и несколько больше консистентности.
С тех пор, как Microsoft подарил нам TypeScript, написание клиентских JavaScript-ов стало занятием гораздо более комфортным. TypeScript принес ощущение типизируемости и прекомпилируемость туда, где их его не хватало. Если вы его еще не пробовали — то обязательно попробуйте (это не реклама, нет). Можно, конечно, много спорить по вопросу «быть или не быть» TypeScript-у в вашем конкретном проекте, но давайте опустим дискуссию и перейдем » — Ближе к телу! — как говорил Ги де Мопассан».
Практический пример
Итак, рассмотрим простой, но достаточно распространенный пример — вам необходимо сделать запрос к серверу, достать информацию о заказе и отобразить её каким-либо образом на страничке в браузере.
Что мы обычно делаем для решения этой задачи? Правильно. Мы делаем POCO модели заказа и метод контроллера, который будет возвращать ее экземпляр, обернутый в JSON. Вот они, наши герои (как вы поняли, я буду убирать лишний код для экономии места):
Моделька
public class OrderViewModel < public string ItemName < get; set; >public int Quantity < get; set; >public decimal Subtotal < get; set; >public bool IsPaid < get; set; >public string ClientName < get; set; >public string Address < get; set; >>
Метод контроллера
public ActionResult GetOrder(int orderId) < var orderVm = new OrderViewModel() < // . тестовые данные . >; return Json(orderVm, JsonRequestBehavior.AllowGet); >
Здесь все более-менее понятно и комментарии, думаю, излишни. Давайте переключимся на клиент.
Чтобы быть предельно понятным, я буду использовать jQuery для ajax-запросов, но при необходимости вы можете заменить его на что-нибудь свое. Как и ранее, я опускаю излишний glue code, а так же создание view, TypeScript-файла, подключение его к станице, установку jQuery из NuGet — это вы все сможете сделать и без меня. Подчеркиваю самую суть (еще раз напоминаю, что этот код на TypeScript):
Код TypeScript
private btnRequest_click() < $.ajax(< url: ‘/Home/GetOrder?orderId=10’, success:this.handleResponse >); > private handleResponse(data: any) < var text = `$, $ ($, $)`; $(‘#divInfo’).text(text); >
Здесь прекрасно все. За исключением того, что принципиально от JavaScript эта конструкция ничем не отличается. Мы получаем с сервера кусок JSON-а, в котором какой-то объект и мы, рассчитывая на то, что у него есть поля ClientName, Address и прочие — выводим его в div.
Звучит не очень стабильно. Если какой-нибудь горе-джуниор удалит из ViewModel-и и из C#-кода, скажем, поле ClientName (или переименует его в целях джуниор-рефакторинга), то все места на фронтенде, где используется такая конструкция — превратятся в детонаторы и будут ждать прихода тестировщика. Ну или end user-а — тут уж кому как повезет. Что же делать? Ответ очевиден — коль скоро мы используем TypeScript, то можно написать тайпинг для этой конкретной ViewModel-и и переписать код вот таким образом:
private handleResponse(data: IOrderViewModel) < var text = `$, $ ($, $)`; $(‘#divInfo’).text(text); >
Да, теперь нам стало несколько комфортнее — мы застраховались от доступа к незадекларированному полю. Но ситуация с джуниором, переименовывающим поле лично мне не дает спокойно спать. Да и написание тайпингов для всех ViewModel-ей… руками… ночью… А если их в проекте сотни? А если тысячи?
Перспективка-то, откровенно, так себе.
Вот тут-то и вступает в игру Reinforced.Typings и начинается решение задачи кардинально другим путем. Итак, открываем PM-консоль (ну или кому удобно — можете сделать это через графический интерфейс) и ставим:
PM > Install-Package Reinforced.Typings
Замечаем в корне проекта новый файл Reinforced.Typings.settings.xml. Он достаточно детально документирован и переписывать все, изложенное в нем здесь я не вижу смысла (если конечно у кого-то из аудитории у меня не все так плохо с английским), предоставив это хабралюдям. Я изменю всего один параметр — это путь к файлу, куда ляжет сгенерированный тайпинг. В моем проекте он вот такой:
$(ProjectDir)ScriptsappServer.ts
После чего, я иду в код модельки и добавляю всего две строчки кода — юзинг на Reinforced.Typings.Attributes и атрибут [TsInterface] над самим классом модельки. Примерно вот так:
using Reinforced.Typings.Attributes; [TsInterface] public class OrderViewModel < // в самом коде модельки ничего не изменилось >
После чего я пересобираю проект (делаю ему Rebuild) и вручную добавляю в Scriptsapp сгенерированный согласно конфигурации Server.ts. Он уже лежит в указанной папке — просто не добавлен в проект. Давайте откроем Server.ts и посмотрим что же в нем такое:
Содержимое Server.ts
// This code was generated by a Reinforced.Typings tool. // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. module Reinforced.Typings.Samples.Simple.Quickstart.Models < export interface IOrderViewModel < ItemName: string; Quantity: number; Subtotal: number; IsPaid: boolean; ClientName: string; Address: string; >>
Вот видите? Чудненько. Теперь задача по написанию тайпингов для ViewModel-ей всего проекта не кажется таким уж страшным делом, не правда ли? Да и удаление-переименование properties ViewModel-и уже не является трагедией: при следующей же сборке проекта тайпинги перегенерируются и TypeScript-код, который на них завязан просто перестанет собираться, в чем вы можете убедиться собственноручно.
Думаю, на этом практическую демонстрацию основной возможности можно закончить, оставив более сложные примеры на следующие статьи и перейти к драматическому заключению.
Драматическое заключение и немного о том-о сем
На самом деле Reinforced.Typings поддерживает много чего. Вот краткий список:
- Автоматические тайпинги делегатов, наследников IEnumerable и IDictionary (если вы используете их в качестве properties)
- Тайпинги для enum-ов и классов (правда, тела методов он перевести в TypeScript автоматически не может. Но это можно сделать самостоятельно — об этом ниже)
- Тайпинги со сложными типами — Reinforced.Typings понимает, что вы используете в классе другой экспортируемый тип и автоматически ставит в том месте full-qualified имя используемого типа. В противном случае — тактично использует any
- Можно раскидать генерируемый код по разным файлам (class-per-file) с помощью соответствующего параметра конфигурации
- Можно добавить /// в генерируемые файлы посредством assembly-атрибута [TsReference]. А в случае с class-per-file, reference на соседние файлы добавляется автоматически
- Можно генерировать, .d.ts-файлы вместо обычного .ts-кода (есть некоторые отличия в синтаксисе)
- Вишенка на тортик — у каждого атрибута присутствует свойство CodeGeneratorType, в котором можно указать тип-наследник от Reinforced.Typings.Generators.ITsCodeGenerator<> (как вариант — унаследоваться от существующего генератора) и сделать свою генерацию шаблонного TypeScript-кода для всего, чего угодно. Таким путем можно дойти до автоматического создания knockout-овских ViewModel-ей прямо из кода серверных ViewModel-ей. В проекте по моему текущему месту работы, я перегрузил генератор кода для экшнов контроллера и сгенерировал таким образом для многих методов js-ный glue code, вызывающий соответствующий метод контроллера с указанными параметрами. Возвращают такие методы q-шный promise (просто потому что я люблю Q.js). Об этом я и расскажу в следующем посте
Из минусов: Автоматически сгенерировать тела методов классов Reinforced.Typings не может — он работает через Reflection. Ну и еще хочется отметить некие проблемы в ситуации когда серверные сущности представляют правильный TypeScript-код, но в уже сгенерированном коде содержится семантическая ошибка (например, удалено поле). В силу особенностей сборки TypeScript-а (он собирается самым первым во всем проекте), вы не сможете пересобрать проект и сгенерировать правильные тайпинги, которые исправят ошибку, пока не поправите ошибку вручную. Но я над этим работаю. Магия MSBuild творит чудеса.
Еще по проекту, как было сказано выше, крайне мало документации (эта статья, да readme на гитхабе). НО! Очень детально расписан XMLDOC и прокомментирован файл настроек. Так что, я думаю, на первое время должно хватить. А там я уже завербую студента-техписателя и сделаю нормальную книгу Reinforced.Typings Best Practices документацию в вики-формате.
В общем-то на сегодня все. Если какие-то вопросы есть — пишите в комментариях. Постараюсь ответить.
Источник: savepearlharbor.com
Как мы делаем проекты: поддержка
Поздравляем, ваш продукт протестирован и отправлен в релиз. Но если вы волнуетесь о том, что он перестанет работать частично или целиком — это правильно.
И дело не в том, что разработчики пишут плохой код. Тестирование выявляет наиболее вероятные ошибки в сборке, но пространство для багов, которые нельзя предусмотреть, всегда остаётся.
Прежде поддержка была пунктом в основном договоре на разработку ПО. Но мы обособили эту услугу, подняв её ценность и значимость.
Пункт в договоре гласил примерно следующее: «Мы сделаем это за n тысяч рублей» (при модели оплаты fixed price) или «Мы даём вам m часов наших услуг по поддержке» (при модели time Material (и это значит, что задача может быть выполнена когда угодно в границах оплаченного времени), либо работа идёт по SLA и клиент платит абонентскую плату (и это значит, что команда бронируется на конкретное количество часов).
Как убрать статус тайпинга в вк на андроид
В формате устной договорённости такие вещи оставлять нельзя.
Преимущества и недостатки техподдержки
- бронирование времени;
- формирование ожиданий с помощью SLA;
- меньшая, чем по допсоглашению, стоимость часов (при условии, если вы реально смотрите на вещи и максимально точно считаете время).
Источник: livetyping.com
Лайв Тайпинг +2
Запись закреплена Лайв Тайпинг
Кто мы и чем можем быть полезны
21 Октября 2017 Лайв Тайпинг
Итак, вы поняли, что вашему бизнесу нужно мобильное приложение. Вы поняли, что это повышает конверсию и привязанность пользователей и выводит продукт на иной качественный уровень.
15 Августа 2017 Лайв Тайпинг
Директор по маркетингу компании Лайв Тайпинг рассказывает, какие вопросы должны задать себе стартаперы, запускающие проект в сфере eTravel.
9 Июня 2017 Лайв Тайпинг
Почему цена разработки приложения может отличаться так сильно и почему не все готовы работать по фиксированной цене? Эта статья адресована менеджерам, предпринимателям и компаниям, которые собираются заказать разработку приложения. Она избавит вас от непонимания и возмущения, связанного с оценкой трудозатрат на разработку ПО, и объяснит, к какой категории клиентов вы относитесь и как эту категорию менять.
Источник: spark.ru