Самый кошерный способ лабать веб-сервисы
на python c фреймворком bottle очень удобно лабать рест-костыли. мне тут понадобилось как-то по работе для пресейла мобильных и браузерных приложений сделать бэкэнд. можно было развернуть клон одной из боевых платформ (несколько монстроузных джава-бегемотов, одно ктухоподобное сишное приложение, пара баз данных), но я забил и на путоне за пол часа наваял затычки для всех нужных методов и всё помещается в два файла - фреймворк и затычка.
А что надо-то? Какой API?
XML и JSON отдавать большого ума не надо.
XML и JSON отдавать большого ума не надо.
Да ничего конкретного - просто, чтобы быть в тренде, на чем щас лабают, а то расплодилось всего. Наверное, стандарт - json, сходить в какое-нить хранилище и т.д.
ASP.NET
А комменты какие-нить будут, чем он крут и круче остальных? Так я сам могу пару десятков названий написать
Няшный C#. ReSharper. Controllable Query. Ну или Linq, но я не рекомендую.
NodeJS + Express 

Опять, хотелось бы еще и комментов
Если что-то из базы дергать, то для ноды сейчас почти все вендоры баз пишут драйвера, шоб работало из коробки. Сильно облегчает написание прототипа и изменение модели в будущем.
ASP.NETМожно ли использовать из линукса? Насколько просто деплоить в линукс?
ASP.NET
ты хотел сказать Web API?
Можно ли использовать из линукса?можно
Насколько просто деплоить в линукс?
sudo apt-get install unzip curl
curl -sSL http://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | DNX_BRANCH=dev sh && source ~/.dnx/dnvm/dnvm.sh
sudo apt-get install libunwind8 gettext libssl-dev libcurl3-dev zlib1g libicu-dev
dnvm upgrade -r coreclr
http://docs.asp.net/en/latest/getting-started/installing-on-...
Из заявленных плюсов NodeJS - обработка большого количества соединений из коробки, что круто для чатов и онлайн игр.
В России вроде не сильно популярна.
Лично мне NodeJS в продакшене использовать еще не доводилось, пока пишу в стол для себя, что называется.
Исходно NodeJS умеет только поднимать web-сервер, работать с файлами/ошибками + возможности языка, всё остальное (работа с базами/логами/шаблонизаторы/сетевые протоколы/прочее) добавляется через менеджер пакетов.
Express - совсем небольшой фреймворк, который по сути добавляет некую структуру обработчиков адресов (route и Middleware), чтобы как то это дело "стандартизировать" в проекте. Можно и не использовать, или воспользоваться одной из альтернатив.
Большой плюс для старта - отличный видеокурс от Ильи Кантора http://learn.javascript.ru/nodejs-screencast с ложкой дегтя в виде устаревшей версии (но не критично), а также учебник по JS.
Из планируемой засады видится выход следующей версии JS.
До кучки
IBM сделает платформу NodeJS стандартом корпоративной разработки
Из доклада http://www.highload.ru/2015/abstracts/1894.html
В России вроде не сильно популярна.
Лично мне NodeJS в продакшене использовать еще не доводилось, пока пишу в стол для себя, что называется.
Исходно NodeJS умеет только поднимать web-сервер, работать с файлами/ошибками + возможности языка, всё остальное (работа с базами/логами/шаблонизаторы/сетевые протоколы/прочее) добавляется через менеджер пакетов.
Express - совсем небольшой фреймворк, который по сути добавляет некую структуру обработчиков адресов (route и Middleware), чтобы как то это дело "стандартизировать" в проекте. Можно и не использовать, или воспользоваться одной из альтернатив.
Большой плюс для старта - отличный видеокурс от Ильи Кантора http://learn.javascript.ru/nodejs-screencast с ложкой дегтя в виде устаревшей версии (но не критично), а также учебник по JS.
Из планируемой засады видится выход следующей версии JS.
До кучки
IBM сделает платформу NodeJS стандартом корпоративной разработки
Из доклада http://www.highload.ru/2015/abstracts/1894.html
В течение последнего года мы разрабатывали проект DMP (Data Management Platform), используя NodeJS для прототипирования. На данный момент проект в большей степени все еще остался на JS и без труда справляется с текущими нагрузками в 10 000 запросов в секунду.
В докладе расскажу, почему остановились именно на NodeJS, хотя выбирали между .NET, Go, NodeJS, Python и Ruby. Почему не жалеем о своем выборе и будем дальше использовать для некоторых проектов.
Gо:
Недавно делал проект, состоящий из нескольких частей: программа для устройств, сервис общающийся с этими устройствами, сервис API. Вначале на Go был написан только сервис с устройствами — впечатления были самыми приятными — а API на Python+Flask. И, последнее ощущалось как какой-то вычислительный метод написанный на этом же питоне, т.е. то, что сам язык делает плохо даже на уровне синтаксиса (итерирование по числовыми диапазонам в питоне так себе), не говоря уж об особенностях на уровне исполнения. Ну вот, API после переписал на Go и попа этого стала мягкой и сухой.
Сам язык тоже приятный: сильно спартанский, с одной стороны и забивший на полезные нововведения, вроде алгебраических типов, которые бы закрыли тему NPD, но, в принципе, жить можно, особенно после питона и плюсов. С другой стороны учли весь этот печальный опыт с классами и наследованием и сделали простые интерфейсы, что подталкивает к более тщательному проектированию и очень хорошо сказывается на читабельности сторонних проектов.
- Статическая типизация, хоть и немного куцая (nilable типы, прежде всего)
- Очень жёсткая структура проекта. Не приходится тратить время, как в питоне, на то, как раскидывать файлы, есть, фактически, только один путь
- Готовая инфраструктура для тестирования
- Единообразная стандартная либа
- Компилируемый, достаточно быстрый
- gofmt, конечно же
Недавно делал проект, состоящий из нескольких частей: программа для устройств, сервис общающийся с этими устройствами, сервис API. Вначале на Go был написан только сервис с устройствами — впечатления были самыми приятными — а API на Python+Flask. И, последнее ощущалось как какой-то вычислительный метод написанный на этом же питоне, т.е. то, что сам язык делает плохо даже на уровне синтаксиса (итерирование по числовыми диапазонам в питоне так себе), не говоря уж об особенностях на уровне исполнения. Ну вот, API после переписал на Go и попа этого стала мягкой и сухой.
Сам язык тоже приятный: сильно спартанский, с одной стороны и забивший на полезные нововведения, вроде алгебраических типов, которые бы закрыли тему NPD, но, в принципе, жить можно, особенно после питона и плюсов. С другой стороны учли весь этот печальный опыт с классами и наследованием и сделали простые интерфейсы, что подталкивает к более тщательному проектированию и очень хорошо сказывается на читабельности сторонних проектов.
Статическая типизация, хоть и немного куцая (nilable типы, прежде всего)Всё жутко напоминает яву. Голую.
Очень жёсткая структура проекта. Не приходится тратить время, как в питоне, на то, как раскидывать файлы, есть, фактически, только один путь
Готовая инфраструктура для тестирования
Единообразная стандартная либа
Компилируемый, достаточно быстрый
Сам язык тоже приятный:Я пробовал че-то по мелочи играться, все прикольно кроме ебанутого синтаксиса языка и конструкций, от которых блевать аж тянет. Если бы не это, реально прикольная система получилась бы из го
Всё жутко напоминает яву. Голую.да, но стоит учитывать, что Go — это DSL для написания сервисов, с вытекающим следствием в виде простоты и удобства этого процесса
потом, решает stdlib. В Go он на удивление полон, решает большую часть задач с достаточным качеством. С джавкой могу сравнивать только с 7-ой версией, которую использовал для программирования под андроид и, знаешь, впечатление было не слишком хорошим: нужно было прочесть файл целиком в строку (выводить для логирования) - нет готового метода, цикл, как в плюсах.
Хочется сделать банальный джойн для списка стрингов - хуюшки, пиши цикл. Ничего сложного, но вторая задача довольно частая.
все прикольно кроме ебанутого синтаксиса языка и конструкций, от которых блевать аж тянет.чем?
Вот, скажем, объявление функции:
func name(x int, y int) int {...}сравним с растом
fn name(x: int, y: int) -> int {...}
Т.е. просто выкинули : и -> как не несущие никакой необходимой функциональности.
Потом, из управляющих конструкций выкинули позорные ( и ), т.к. они обязательно блочные. В тех же плюсах у меня всегда блоки и при этом непонятно зачем скобки.
if a > b {
...Ну и т.д. Всё нормуль, мне нравится. Синтаксис совершенно не сишный, несмотря на { и }, но это не недостаток, а работа над очевидными ошибками. Попробуй пописать, что-ли, немного, привыкнуть. Я как-то быстро влился и перестал его замечать.
func name(x int, y int) int {...}Сравним лучше с модным Swift:
func name(x: Int, y: Int) -> Int {...}
Сравним лучше с модным Swiftв котором типа "иксепшены" в виде магии над алгебраическими типами? Магия — это очень плохо, особенно тогда, когда код без этих иксепшенов ненамного длиннее, если вообще.
ага, и ещё там классические классы с наследованием. Это вообще серьёзно?
Опустим "интерфейсы за минимальное время выражают то, что пытаются сказать классы". Рассмотрим одну важную практическую задачу. Взаимодействие с веб-сервисами. JSON-ы, сериализация, десериализация.
В расте, в котором только интерфейсы, структуру можно пометить как RustcEncodable и RustcDecodable. Компилятор автоматически реализует соответствующие интерфейсы, которые обеспечивают пробегание полей. И после этого структуры можно скармливать всяким JSON/Yaml/whatever сериализаторам и десериализаторам. Где это в swift-е? Фича нужная, почему до сих пор не запилена? Как это сделать для свифтовых классов? Опять магия?
Нене, я не пытаюсь сказать, что Swift молодец. Go мне нравится больше.
Просто даже Swift взял объявление функций у Go (ну, и у похожих языков), а не у Java / C.
Просто даже Swift взял объявление функций у Go (ну, и у похожих языков), а не у Java / C.
Сорри, люблю побрюзжать, особенно когда есть повод )
Сорри, я неправильно выразился: не весь синтаксис кривой, а отдельные конструкции. Пример с функциями, что ты привел - все ок, никаких претензий нет. К сожалению, че-то не могу сходу вспомнить, что меня конкретно раздражало в нем, когда я пытался писать - больше пол года прошло, нужно поковыряться в документации (я щас не беру в рассмотрение такие высокоуровневые идеи как исключения против коды возврата или отсутствие дженериков, хотя в инете пишут, что без второго бывает тяжко). Но вот, например, на днях на хабре была статья. Там вот такая веселая конструкция для вставки элемента в слайс была (при этом, как говорят, без дженериков это даже нормально не завернуть во что-нить приличное):
numbers = append(numbers[:2], append([]int{3}, numbers[2:]...)...)
numbers = append(numbers[:2], append([]int{3}, numbers[2:]...)...)
не append, который slice = append(slice, slice2...) ?
upd начал читать, дошёл до "не могу вспомнить", сразу понял, что это про слайс
ну да, этот момент самый странный
upd начал читать, дошёл до "не могу вспомнить", сразу понял, что это про слайс

ну да, этот момент самый странный
numbers = append(numbers[:2], append([]int{3}, numbers[2:]...)...)Эта операция имеет линейное время выполнения. На мой взгляд, совершенно правильно, что медленные операции выглядят по-уродски.
Если хочется быстро вставлять в середину списка, разумнее использовать linked list. И вот тут мы наступаем на реальную проблему Go: из-за отсутствия генериков довольно много стандартных структур данных и коллекций в stdlib отсутствуют.
Эта операция имеет линейное время выполнения. На мой взгляд, совершенно правильно, что медленные операции выглядят по-уродски.Ты умеешь делать вставку по индексу в список за время, меньшее чем линейное?

Ну, во-первых, у нас уже может быть на руках нужный курсор. Во-вторых, можно иметь дополнительную хеш-таблицу, которая будет выдавать нам указатель на интересующий элемент списка. Можно придумать и более экзотические варианты, все зависит от нашей задачи.
Линейное время - это не значит, что нигде не используется. А, во-вторых, не знаю, что там с выделениями памяти в Го - насколько хорошо они работают, но частенько проще двинуть массив, чем память выделить. Следуя подомной логике, нужно вообще запретить компиляцию вложенных циклов - там же вообще квадрат будет, ну или чтобы обойти это ограничение, нужно десять страниц кода написать - чтобы ты точно знал, что хочешь именно квадрата.
Это как когда-то были споры в С++. Что нельзя перегружать операторы, т.к. они скрывают то, что операция может занимать значительное время. А вот, если вместо оператора +, будет функция add, то сразу становится ясно, что это долгая операция.
Это как когда-то были споры в С++. Что нельзя перегружать операторы, т.к. они скрывают то, что операция может занимать значительное время. А вот, если вместо оператора +, будет функция add, то сразу становится ясно, что это долгая операция.
Держи вот, сравнивай, какой из сортов этого самого тебе больше по душе: http://todomvc.com/
Как по мне, имхо лучше не тратить время на изучение всей этой белиберды и ограничиться чем-то легким и действительно полезным типа шаблонизатора на mustache. А когда придёт время и в браузерах запилят ecma6, то и его выкинуть к чертям.
Как по мне, имхо лучше не тратить время на изучение всей этой белиберды и ограничиться чем-то легким и действительно полезным типа шаблонизатора на mustache. А когда придёт время и в браузерах запилят ecma6, то и его выкинуть к чертям.
ну или чтобы обойти это ограничение, нужно десять страниц кода написатьВ Go именно так и сделали. Там где в нормальных языках будет одна строчка с filter/map/join, в Go будет 10 строк с императивными циклами.
Это как когда-то были споры в С++. Что нельзя перегружать операторы, т.к. они скрывают то, что операция может занимать значительное время.Да-да-да, и если сатана добавит нам еще возможностей, мы должны быть твердыми и не использовать их.

Проблема, что вашу ч0рную магию потом ещё поддерживать как-то.
У меня в компании пишут код на go, выглядит так:
Мне при виде этого кода хочется приделать либо монады, либо исключения, но в go нет ни того, ни другого AFAIK.
if err := mw.CropImage(thumb.width, thumb.height, thumb.x, thumb.y); err != nil {
response.Result = false
response.Message = err.Error()
logger.error.Println(err)
return
}
if err := mw.ResizeImage(uint(CONF_CUTTER_THUMBNAIL_SIZE), uint(CONF_CUTTER_THUMBNAIL_SIZE), imagick.FILTER_LANCZOS2, 1.3); err != nil {
response.Result = false
response.Message = err.Error()
logger.error.Println(err)
return
}
if err := mw.WriteImage(destination + DS + "preview.jpg"); err != nil {
response.Result = false
response.Message = err.Error()
logger.error.Println(err)
return
}
var destinationPublic string
if CONF_UPLOAD_TARGET == "s3" {
i := "http://" + CONF_UPLOAD_BUCKET + "." + CONF_UPLOAD_ENDPOINT
destinationPublic = filepath.Dir(strings.Replace(request.Source, i, "", 2))
err = uploadDir(destination, destinationPublic)
} else {
destinationPublic = filepath.Dir(request.Source)
err = saveDir(destination, destinationPublic)
}
if err != nil {
response.Result = false
response.Message = err.Error()
logger.error.Println(err)
} else {
os.RemoveAll(destination)
logger.trace.Printf("Published files in (%s)%s from %s", CONF_UPLOAD_TARGET, destinationPublic, destination)
}
if err != nil {
response.Result = false
response.Message = err.Error()
logger.error.Println(err)
}else {
logger.trace.Println("Ok: ", destination, "=>", filepath.Dir(request.Source))
}
Мне при виде этого кода хочется приделать либо монады, либо исключения, но в go нет ни того, ни другого AFAIK.
Мне при виде этого кода хочется приделать либо монады, либо исключения, но в go нет ни того, ни другого AFAIK.препроцессор же

Это не идиоматичный код на Go. Даже если не пытаться угадывать какие высокоуровневые изменения можно сделать, код может выглядеть чуть лучше:
Из того, что выглядит лишним, но нельзя убрать без изменения кода вокруг:
1. response должен иметь поле err и не иметь поля Result и Message. Вместо Result проверять err == nil. Message внутри err.
2. выглядит так, что тут требуется функция, которая возвращает err. Запись в response надо делать либо в defer, либо в caller. Тогда будет еще короче:
Правда, рекомендуется добавлять дополнительную информацию в ошибку, если она обрабатывается не на месте, а переходит на более высокий уровень:
3. Приведение CONF_CUTTER_THUMBNAIL_SIZE к uint выглядит подозрительным. Если это константы, то они (могут быть) typeless: получают тип в месте использования.
4. Очень подозрительный код по конструированию пути:
Но непонятно, как именно надо менять, т.к. неясно, что такое DS.
5. Названия переменных могут быть короче. В частности, response -> resp, destination -> dest, request -> req.
6. Если есть несколько однотипных операций, примененных подряд, зачастую удобно занести их в массив и запускать их в цикле, но конкретного совета дать тяжело, т.к. кусок кода слишком мал.
defer func() {
if !response.Result { logger.error.Println(response.Message) }
}()
if err := mw.CropImage(thumb.width, thumb.height, thumb.x, thumb.y); err != nil {
response.Result = false
response.Message = err.Error()
return
}
if err := mw.ResizeImage(uint(CONF_CUTTER_THUMBNAIL_SIZE), uint(CONF_CUTTER_THUMBNAIL_SIZE),
imagick.FILTER_LANCZOS2, 1.3); err != nil {
response.Result = false
response.Message = err.Error()
return
}
if err := mw.WriteImage(destination + DS + "preview.jpg"); err != nil {
response.Result = false
response.Message = err.Error()
return
}
var destinationPublic string
if CONF_UPLOAD_TARGET == "s3" {
i := "http://" + CONF_UPLOAD_BUCKET + "." + CONF_UPLOAD_ENDPOINT
destinationPublic = filepath.Dir(strings.Replace(request.Source, i, "", 2))
} else {
destinationPublic = filepath.Dir(request.Source)
err = saveDir(destination, destinationPublic)
}
if err != nil {
response.Result = false
response.Message = err.Error()
return
}
os.RemoveAll(destination)
logger.trace.Printf("Published files in (%s)%s from %s", CONF_UPLOAD_TARGET, destinationPublic, destination)
Из того, что выглядит лишним, но нельзя убрать без изменения кода вокруг:
1. response должен иметь поле err и не иметь поля Result и Message. Вместо Result проверять err == nil. Message внутри err.
2. выглядит так, что тут требуется функция, которая возвращает err. Запись в response надо делать либо в defer, либо в caller. Тогда будет еще короче:
if err := mw.CropImage(thumb.width, thumb.height, thumb.x, thumb.y); err != nil {
return err
}
Правда, рекомендуется добавлять дополнительную информацию в ошибку, если она обрабатывается не на месте, а переходит на более высокий уровень:
if err := mw.CropImage(thumb.width, thumb.height, thumb.x, thumb.y); err != nil {
return fmt.Errorf("CropImage: %v", err)
}
3. Приведение CONF_CUTTER_THUMBNAIL_SIZE к uint выглядит подозрительным. Если это константы, то они (могут быть) typeless: получают тип в месте использования.
4. Очень подозрительный код по конструированию пути:
destination + DS + "preview.jpg"
Но непонятно, как именно надо менять, т.к. неясно, что такое DS.
5. Названия переменных могут быть короче. В частности, response -> resp, destination -> dest, request -> req.
6. Если есть несколько однотипных операций, примененных подряд, зачастую удобно занести их в массив и запускать их в цикле, но конкретного совета дать тяжело, т.к. кусок кода слишком мал.
Правда, рекомендуется добавлять дополнительную информацию в ошибку, если она обрабатывается не на месте, а переходит на более высокий уровень:В проектах над которыми я работал, обычно обработать ошибку на месте было невозможно. Если не работает файловая система или сеть, то надо сразу упасть, но упасть так чтобы ошибка надежно попала в логи и мониторинг для админов.
Тут глядя на код трудно сразу понять, все ли if правильно расставлены, на мой взгяд легко допустить ошибку потому что код зашумленный. В результате одна операция выполнится неуспешно, а остальные продолжат работу, итог - битые данные. Особенно это опасно, потому что сценарий "не удалось записать в файл" никто никогда не тестирует.
Тут глядя на код трудно сразу понять, все ли if правильно расставлены, на мой взгяд легко допустить ошибку потому что код зашумленный.Я согласен с оценкой, что код зашумленный (см мое предыдущее сообщение), но в этом вина не языка.
Я согласен с оценкой, что код зашумленный (см мое предыдущее сообщение), но в этом вина не языка.В твоей версии вот это блок три раза повторяется:
response.Result = false
response.Message = err.Error()
return
Да, но только потому, что мне не хватило контекста для правильного изменения кода.
Если запостишь кусок подлиннее, я смогу сделать код значительно чище.
Если запостишь кусок подлиннее, я смогу сделать код значительно чище.
"Как-то" все равно не получится, и количество возможностей тут роли не играет.
Оставить комментарий
agent007new
Какой щас самый крутой способ лабать веб-сервисы (ну которые потом аяксом будет кто-нить дергать)? Тот, который знаешь - это понятно. Вопрос чисто абстрактный - никакой конкретной задачи не стоит. Питон с джанго, фласком, там еще чем, жаба, го, еще что? А то щас наплодилось языков и фреймворков и вот какая из этих связок "самая-самая"? Так, ради флуда