LINUX.ORG.RU

На что обращают внимание в тестовых заданиях на С++?

 


3

5

Сейчас нахожусь в поисках работы. Один из языков, который у меня указан в резюме это С++. Не разрабатывал на нем уже 4-5 лет, но базовые знания не должны были пропиться. :) Столкнулся с тем, что сейчас любят давать тестовые задания на дом, в которых нужно написать tcp клиент/сервер. Задания довольно простые, типа клиент отправляет раз в секунду число на сервер, сервер делает с ним некую манипуляцию и отсылает обратно клиенту. Сервер должен поддерживать множество клиентов, клиентский интерфейс не должен фризиться, в общем стандартный набор требований. Выслали мне одно такое задание, написал, отправил им. И тут приходит ответ - «К сожалению, по результатам реализации тестового задания, мы не готовы предложить вам дальнейшее участие в конкурсе на замещение данной позиции.» Я как минимум рассчитывал на то, что второй раунд быть был обязан. Главное понять не могу, что им не понравилось. Приложение требованиям соответствует, не падает, архитектура вроде не говеная - стандартная, warning-ов нет, в сроки уложился, написано на Qt. Сейчас делаю подобное задание для другой конторы и думаю как бы не вляпаться снова. Есть тут спецы по подобным тестам? Ссыль на выполненный тест

Тест полного задания: Необходимо создать клиентское и серверное приложения с помощью C++ и Qt

1. Сервер: по заданному порту, принимает соединения по TCP от клиентов. В случае если приходит число, умножает его на 2 и возвращает значение клиенту. Поддерживает «неограниченное» количество подключений.

2. Клиент: Запрашивает у пользователя адрес сервера, порт и диапазон чисел, с помощью GUI. Присоединяется к серверу и посылает ему в цикле случайное число из диапазона. В окне выводит информацию о том, какое число было послано и какое было получено. После чего ждет 1000мс и посылает следующее. Часть, занимающуюся коммуникацией по TCP, необходимо выполнить в отдельном потоке.

★★

Последнее исправление: Booster (всего исправлений: 2)
Ответ на: комментарий от asaw

я просто имел в виду, что этот момент никак не обработан. уж конвертацию в строку с заданной точностью можно было запилить.

vvviperrr ★★★★★
()
Ответ на: комментарий от Booster

понял, у тебя 2 версии сервера. еще псевдорандом рандом у тебя не инициализируется.

vvviperrr ★★★★★
()
Ответ на: комментарий от vvviperrr

Тест полного задания: Необходимо создать клиентское и серверное приложения с помощью C++ и Qt

asaw ★★★★★
()

Особо код не смотрел, но за генерацию исключений в КОНСТРУКТОРЕ вам вполне могли впоять отказ на должность C++ разработчика ...

Да и ловля исключений по значению вместо ссылки явно указывает на малый опыт разработки на С++.

Отсутствие контроля памяти, явное принебрежение врнингами при сборке (не инициализированые переменные, отсутвие возврата в не void методах)

Не понятен смысл использования QT как такового, при тестовом задании как правило желают увидеть уровень владения некоторым API (WIN32, POSIX) прикладные библиотеки здесь излишни (разве что вы претендовали на позицию QT разработчика).

zaz ★★★★
()
Ответ на: комментарий от zaz

Особо код не смотрел, но за генерацию исключений в КОНСТРУКТОРЕ вам вполне могли впоять отказ на должность C++ разработчика ...

В конструкторе не страшно и даже иногда хорошо. В деструкторе - очень плохо.

asaw ★★★★★
()
Ответ на: комментарий от asaw

В конструкторе не страшно и даже иногда хорошо. В деструкторе - очень плохо.

По хорошему в конструкторе приемлемым является только OutOfMemoryException. А генерить 3 разных эксепшена и руками чистить поля это черевато ликами (по памяти или ресурсам), это хорошо что есть только 1 ресурс (сокет) а не 100. Тут либо нужен нормальный init/create либо все обварачивать в смартпоинтеры - что н всегда практично/нужно ...

zaz ★★★★
()
Ответ на: комментарий от zaz

Ну если есть возможность генерации исключений в конструкторе, то тогда да - везде RAII в реализации. А поскольку часто невозможно с уверенностью сказать может ли какой-нибудь из членов или предков сгенерировать исключение при конструировании, то лучше по умолчанию использовать RAII, а не использовать только в тех редких случаях, когда нужен супероптимизированный код.

asaw ★★★★★
()

Ссыль на выполненный тест

на гитхаб такое не берут?

anonymous
()
Ответ на: комментарий от zaz

отсутвие возврата в не void методах

Это в main что ли? Не нужно.

mix_mix ★★★★★
()
Ответ на: комментарий от asaw

использовать RAII, а не использовать только в тех редких случаях, когда нужен супероптимизированный код.

щито? как одно к другому?

anonymous
()
Ответ на: комментарий от anonymous

Точно так же, как и в других местах - используешь RAII для членов.

asaw ★★★★★
()
Ответ на: комментарий от zaz

Не на малый опыт, а на то что заржавел после 5 лет неиспользования. Откуда инфа про исключения в конструкторах? Как раз наоборот их советуют использовать, чтобы не было недообъектов. Ворнинги только в winsocket сервере, можете забить на него. Только не инит, прекратите эти замашки.

Booster ★★
() автор топика
Последнее исправление: Booster (всего исправлений: 4)

Главное понять не могу, что им не понравилось.

Не Dr.Web кстати? А то они так любят.

sT331h0rs3 ★★★★★
()
Ответ на: комментарий от zaz

при тестовом задании как правило желают увидеть уровень владения некоторым API (WIN32, POSIX)

Ну и кому интересно смотреть, как претендент пердолится с низкоуровневым API без всякой на то причины?

---

По моему опыту в тестовом задании в основном обращают внимание на:

  • документация, программа собирается или устанавливается, запускается, проходит acceptance tests и свои юнит-тесты.
  • качество декомпозиции, очень часто приходят решения «в лоб»: listen, accept, read, process, responce иногда в одном классе и даже функции.
  • ясность, предсказуемость кода
staseg ★★★★★
()
Ответ на: комментарий от staseg

Ну и кому интересно смотреть, как претендент пердолится с низкоуровневым API без всякой на то причины?

Мне интересно, чтобы понять насколько он владеет предметной областью, также это даст почву для дальнейшего интервью (почему использовались эти API/вызовы, какие есть аналоги в чом их приимущества/недостатки). По крайней мере это на много позновательней чем смотреть как он реализовал тестовое (совсем не сложное) задание с помощью високоуровневой библиотеки которая в компании не используется и использоватся не будет. Есще и не факт что человек который будет смотреть его тест имеет достаточные знание для анализа кода написаного с использованием этой библиотеки. Вобще как правило соискатели спрашивают (есле не указано в ТЗ) с применением каких технологий ожидается исполнение тестового задания.

zaz ★★★★
()
Ответ на: комментарий от zaz

Мне интересно, чтобы понять насколько он владеет предметной областью

Вот так из средства сетка становится предметной областью. Нет, она конечно может ею быть в узком круге задач, но где эти задачи и где «раз в секунду перднуть в сокет»?

это даст почву для дальнейшего интервью
По крайней мере это на много позновательней чем смотреть как он реализовал тестовое (совсем не сложное) задание

Это задание можно реализовать множеством разных способов, интересно должно быть смотреть на архитектуру закладываемого приложения, расширяемо ли оно, масштабируемо, легко ли для понимания и поддержки. Вот где почва для настоящего разговора. Или в задании должны быть какие-то хардкорные лимиты, тогда и задание другое, и разговор соответственно тоже.

с помощью високоуровневой библиотеки которая в компании не используется и использоватся не будет

Это вообще что-то из области старого пердунства.

Еще и не факт что человек который будет смотреть его тест имеет достаточные знание для анализа кода написаного с использованием этой библиотеки.

Вот, вот самая суть! Работать с таким человеком – страдание, лучше оставить его в своем мирке и не трогать, совсем.

Вобще как правило соискатели спрашивают (есле не указано в ТЗ) с применением каких технологий ожидается исполнение тестового задания.

Вообще ТС явно указал в ОП Qt, но я не знаю, какую из версий его поста ты видел. Мне на последнем тестовом задании сказали использовать любые технологии, которые смогут упростить решение – я считаю это идеальной формулировкой, которая должна быть в подавляющем большинстве вакансий, связанных с разработкой бизнес-логики.

staseg ★★★★★
()
Ответ на: комментарий от staseg

Интересно насчет документации и тестов. Практически везде просят документировать, но вопрос как? Есть такое понятие как самодокументирующийся код, вроде такие места документировать не надо, но когда пишешь все кажется самодокументирующимся. Где искать середину? И еще несмотря на то, что в заданиях просят, а в их самом коде никакой документации. Мне один гуру давно сказал, что сигнатура функции лучше любого комментария и он таки действительно был гуру. Насчет юнит-тестов. Известно, что все тестировать бессмысленно, в основном всякие расчеты и парсеры. В данном задании лично я не вижу ни одного теста.

Booster ★★
() автор топика
Ответ на: комментарий от Booster

Документация – это как минимум README(.md). Пишешь, что это за программа, какую проблему решает, если она реализует часть какой-то большой идеи, описываешь, как ее применять в уже существующей экосистеме. Дальше обычные разделы: зависимости, сборка, конфигурирование, примеры использования. Возможно описание протокола/API, но это по ситуации.

Понятно, что часть этой информации заведомо известна принимающей стороне, но а) ты делаешь законченное решение, б) ты описываешь свое видение задачи, т.к. зачастую даже в подробно расписанных заданиях упускают какие-то детали, показавшиеся очевидными при его написании. Это приводит к спору «а я понял так, ну давайте предположим, а я щас переделаю,..» и очевидному отказу. Докой ты утверждаешь: я сделал так, никаких вопросов и соплей, работодатель сопоставит твое решение со своим заданием, и даже если твое понимание будет несколько расходиться с предполагаемой задачей, тебе это даст фору перед кучей дебильных соискателей с архивами исходников и табличкой «я все сделал, теперь ебитесь сами».

А вот именно документировать код не нужно, он должен быть понятным. Достаточно описания архитектуры (взаимосвязи модулей) и протоколов. И лучше отдельным файлом.

По тестам я в целом не большой фанат. По-хорошему юнит-тестами стоит покрывать любые достаточно сложные вычисления, сложность определяется субъективно. Но таки обычно хватает тестов API. Ну это мое мнение как разработчика, QA конечно со мной не согласится :)

staseg ★★★★★
()
Ответ на: комментарий от zaz

Тут либо нужен нормальный init/create

Двухфазная инициализация - весьма спорная штука.

DarkEld3r ★★★★★
()
Ответ на: комментарий от zaz

API, как и лишние библиотеки, вообще нет смысла использовать, если в этом нет необходимости. Клепать софт на чём-то высокоуровневом гораздо быстрее и менее геморройно чем ковырять API или ASM. То что код будет работать на 1% медленнее из-за какой-то обёртки обычно того не стоит.

peregrine ★★★★★
()
Ответ на: комментарий от Booster

readme, комментарии в коде, если делаешь большую либу, то лучше сразу использовать doxygen. У тебя вообще комментариев нет. Это плохо.

peregrine ★★★★★
()
void Client::onStateChanged(QAbstractSocket::SocketState state)
{
    emit stateChanged(state);
}

void Client::onValueReceived(double sentValue, double result)
{
   emit valueReceived(sentValue, result);
}

вот это не нужно - можно соединить сразу сигналы.

    int port = DEFAULT_PORT;
    if (argc > 1)
    {
        try
        {
            port = std::stoi(std::string(argv[1]));

для парсинга аргументов у Qt есть свои инструменты

Server.exe завершился с кодом -1073741510 не удаляются ресурсы перед завершением, треды не останавливаются (привет while(true))

Имена методов с заглавной, qt4 стиль connect, if без {}

anonymous
()
Ответ на: комментарий от Booster

Откуда инфа про исключения в конструкторах? Как раз наоборот их советуют использовать, чтобы не было недообъектов

Да где-то встречалось. Может Майерс писал. Основная проблема в том, что деструктор для несозданного класса не вызовется. А этот класс может быть унаследован от другого класса. Привет memory leak. Обратные советы ты читал на говнофоруме, читай книги.

Burns
()
Ответ на: комментарий от Burns

Вы что-то путаете. Деструктор данного класса вызываться и не должен, так как объект еще не был создан. Деструкторы уже созданных/не динамических членов вызваться обязаны. Что касается динамических объектов, то да это проблема, которую можно и даже нужно обходить с помощью умных указателей. Я обратные советы на говнофорумах не читал, я читал Страуструпа и его ученика Липмана которые не запрещали использовать исключения в конструкторах. Отложенная инициализация имеет свое применение, но использовать ее везде это абсурд. Хотите еще пообсуждать С++, я не против, вперед.

Booster ★★
() автор топика
Последнее исправление: Booster (всего исправлений: 1)
Ответ на: комментарий от Booster

Да, прошу прощения, подзабыл этот момент. Возможные утечки были в том же конструкторе до исключения, решение Вы назвали. Также забыл главное правило данного форума - не выпендриваться, т.к. всегда найдутся люди, разбирающиеся в вопросе лучше тебя)

Burns
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.