1131 Очень хорошо спросили. +1. Конечно, это будущие полезные ссылки для меня. Также @Aaron и другие добавили ценность для обсуждения. Как и Ruby, этот вопрос в равной степени применим к другим средам программирования.
Я использовал первые два варианта. Первый для многочисленных приложений и второй для моего проекта с открытым исходным кодом Cowoop
Вариант 1
Этот, без сомнения, самый популярный. Но я считаю, что реализация очень много http-иш. Каждый исходный код API относится к объекту запроса. Таким образом, код API - это больше, чем просто код ruby / python / другого языка.
Вариант 2
Я всегда любил это.
Эта опция также подразумевает, что HTML не генерируется во время выполнения на сервере. Это отличает вариант 2 от варианта 3. Но он создается как статический html с использованием сценария сборки. При загрузке на стороне клиента эти HTML будут вызывать сервер API как клиент JS API.
Разделение интересов является большим преимуществом. И очень по вашему вкусу (и моему) бэкэнд-эксперты внедряют бэкэнд-API, тестируют их легко, как обычный языковой код, не беспокоясь о коде запроса framework / http.
Это действительно не так сложно, как звучит на внешней стороне. Вызовы API и полученные данные (в основном, json) доступны для вашего клиентского шаблона или MVC.
Меньше обработки на стороне сервера. Это означает, что вы можете перейти на обычное оборудование / менее дорогой сервер.
Легче тестировать слои независимо, проще создавать документы API.
У него есть некоторые недостатки.
Многим разработчикам это сложно и сложно понять. Таким образом, есть вероятность, что архитектура может подвергнуться критике.
i18n / l10n сложно. Поскольку HTML по сути генерируется, время сборки статично, для каждого поддерживаемого языка требуется несколько сборок (что не обязательно плохо). Но даже при этом вы можете иметь угловые случаи около l10n / i18n и вам нужно быть осторожным.
Вариант 3
В этом случае внутреннее кодирование должно совпадать со вторым вариантом. Большинство пунктов для варианта 2 применимы и здесь.
Веб-страницы отображаются во время выполнения с использованием шаблонов на стороне сервера. Это значительно облегчает работу с более устоявшимися / принятыми методами. Может быть на один HTTP-вызов меньше для некоторого существенного контекста, необходимого для рендеринга страницы, такого как пользователь, язык, валюта и т. Д. Таким образом, обработка на стороне сервера увеличивается при рендеринге, но, возможно, компенсируется меньшим количеством http-вызовов к API-серверу.
Теперь, когда страницы отображаются на сервере, интерфейс теперь больше связан с программной средой. Это может даже не учитываться для многих приложений.
Как я понимаю, Twitter может выполнять свою первоначальную визуализацию страниц на сервере, но для обновления страниц он все еще имеет некоторые вызовы API и шаблоны на стороне клиента для манипулирования DOM. Таким образом, в таком случае у вас есть двойные шаблоны для обслуживания, что добавляет некоторые накладные расходы и сложность. Не каждый может позволить себе этот вариант, в отличие от Twitter.
Я использую Python. Я использую JsonRPC 2.0 вместо REST. Я предлагаю REST, хотя мне нравится идея JsonRPC по разным причинам. Я использую ниже библиотеки. Кто-то, рассматривающий вариант 2/3, может найти его полезным.
Вариант 3!.
В общем, я успешно использовал вариант 2, но теперь для простоты склоняюсь к варианту 3. Генерация статических HTML-страниц с помощью скрипта сборки и их обслуживание на одном из сверхбыстрых серверов, специализирующихся на обслуживании статических страниц, очень заманчиво (вариант 2).
This method will work for iterators that are not random-access iterators but it can still be specialized by the implementation to be no less efficient than iter += 2
when used with random-access iterators.
You could use the 'assignment by addition' operator
iter += 2;
http://www.cplusplus.com/reference/std/iterator/advance/
std::advance(it,n);
where n is 2 in your case.
The beauty of this function is, that If "it" is an random access iterator, the fast
it += n
operation is used (i.e. vector<,,>::iterator). Otherwise its rendered to
for(int i = 0; i < n; i++)
++it;
(i.e. list<..>::iterator)
If you don't know wether you have enough next elements in your container or not, you need to check against the end of your container between each increment. Neither ++ nor std::advance will do it for you.
if( ++iter == collection.end())
... // stop
if( ++iter == collection.end())
... // stop
You may even roll your own bound-secure advance function.
If you are sure that you will not go past the end, then std::advance( iter, 2 ) is the best solution.
The very simple answer:
++++iter
The long answer:
You really should get used to writing ++iter
instead of iter++
. The latter must return (a copy of) the old value, which is different from the new value; this takes time and space.
Note that prefix increment (++iter
) takes an lvalue and returns an lvalue, whereas postfix increment (iter++
) takes an lvalue and returns an rvalue.