Для многих анонимных экспертов, громогласно и авторитетно заявляющих о том, что C++у не место в современном мире, может быть удивительно, но C++ применяется в Web-е не так уж и редко. Может и не напрямую в Web-е, но вот для отдачи JSON-ов и прочей дряни в RESTful-микросервисной архитектуре C++ используется регулярно. И C++ных фреймворков для этих целей, разной степени продвинутости, можно сходу назвать с полдюжины (а если подумать-повспоминать, то и еще больше).
Не мне анализировать причины этого, т.к. я, так уж получилось, лицо заинтересованное и мне выгодно, чтобы C++ применялся в такого рода проектах еще активнее.
Но, полагаю, одна из причин -- это эффективность.
Когда владельцу сервиса приходится платить свои кровные за аренду серверов, то для его кошелька разница между обслуживанием тысячи запросов в секунду и десятью тысяч запросов в секунду на одном и том же железе, полагаю, таки ощутима.
Ну а раз эффективность -- это одна из причин использовать C++, то, полагаю, C++ные фреймворки для поддержки HTTP/REST, должны бы подходить к этому аспекту с тщанием, ведь так?
Ага, я тоже так думал.
Пока не довелось заглянуть в потроха C++ REST SDK от самого Microsoft.
В частности, в реализацию вспомогательной функции split_path.
Был, мягко говоря, удивлен:
std::vector<utility::string_t> uri::split_path(const utility::string_t& path) { std::vector<utility::string_t> results; utility::istringstream_t iss(path); iss.imbue(std::locale::classic()); utility::string_t s; while (std::getline(iss, s, _XPLATSTR('/'))) { if (!s.empty()) { results.push_back(s); } } return results; } |
Т.е. для того, чтобы уже имеющуюся строку разбить на фрагменты, мы эту самую строку сперва копирую внутрь объекта std::istringstream, потом используем std::getline для того, чтобы разделить ее в местах '/'.
Мне кажется, что у всех, кто хоть сколько-нибудь программировал на C++ и хоть что-то слышал про производительность std::istream-ов, должен был бы возникнуть вопрос WTF.
Между тем, реализация аналогичного split_path в лоб посредством простого цикла пишется буквально за 20 минут вместе с набором unit-тестов. У меня в рамках C++17 получилось вот так:
std::vector<std::string> split_path(std::string_view path) { std::vector<std::string> result; while(!path.empty()) { if(auto p = path.find('/'); p != std::string_view::npos) { auto fragment = path.substr(0u, p); path = path.substr(p + 1u); if(!fragment.empty()) result.emplace_back(fragment); } else { result.emplace_back(path); path = std::string_view{}; } } return result; } |
По общему количеству строк не сильно больше. По производительности -- преимущество раза в три:
Да, я понимаю, что string_view из C++17 -- это немного читерство. Но даже в рамках C++03 можно написать не менее эффективно, просто кода будет чуть побольше.
А теперь позвольте мне не сдерживаться, а побомбить.
У проекта больше 7k звезд на GitHub.
Проектом занималась большая корпорация, с поставленными процессами, тщательным отбором на входе (несколько раундов собеседований и т.д.).
А в коде вот такое.
Как так то?
Вот ей богу, если придется искать работу наемным программистом и потребуется пройти несколько стадий собеседований с online-кодингом, то вряд ли получится сдержаться и не послать куда подальше. Впрочем, на эту тему в блоге уже были соответствующие размышлизмы.
А тем временем программист на Java просто пишет:
ОтветитьУдалитьString[] parts = string.split("/")
;)
@еао197
ОтветитьУдалитьДа, там будут пустые строки тоже.