Entrevista alternativa para un puesto de desarrollador de software

En el contexto de las discusiones que retumban aqu铆 en Habr茅 sobre acertijos algor铆tmicos y entrevistas en Yandex, record茅 c贸mo uno de mis amigos, que trabaja para una empresa bastante grande (no rusa), una vez me ofreci贸 un problema de las entrevistas que realizan. Ahora el problema ha cambiado (encontraron un ejemplo m谩s genial del c贸digo), as铆 que con su permiso publico la versi贸n anterior aqu铆.





Un candidato que lleg贸 al puesto de desarrollador no tuvo problemas algor铆tmicos, no fue conducido a trav茅s de los salvajes del lenguaje, sino que simplemente se le dio un c贸digo para su revisi贸n. C贸digo de un proyecto real que una vez intent贸 congelar a un junior verde. Afortunadamente, lo notaron a tiempo.





Se sugiri贸 hacer lo siguiente:





  1. Examine el c贸digo y adivine en pocas palabras lo que hace. (todo est谩 bastante bien documentado en el proyecto, pero las bibliotecas de terceros con documentaci贸n y comentarios a veces tienen problemas, y los desarrolladores deben comprender lo que sucede all铆)





  2. Realice una revisi贸n del c贸digo, se帽ale los lugares sospechosos y malos y sugiera c贸mo se pueden mejorar o rehacer. Puedes hacer cualquier pregunta y buscar en Google lo que quieras.





El c贸digo est谩 en C ++, aunque la mayor铆a de los errores pueden ser encontrados incluso por desarrolladores en otros lenguajes. El c贸digo era algo como esto:





class SomeBusServiceClient {
public:
  SomeBusServiceClient();
  virtual ~SomeBusServiceClient();
  bool CallAsync(const std::string &uri, const std::string &param,
                 const misc::BusServiceClient::ResponseCB &callback);
  bool CallSync(const std::string &uri, const std::string &param,
                const misc::BusServiceClient::ResponseCB &callback);

private:
  misc::BusServiceClient ss_client_;

  static const int kSleepMs = 100;
  static const int kSleepCountMax = 50;
};

class SpecificUrlFetcher : public UrlFetcher {
public:
  SpecificUrlFetcher();
  virtual ~SpecificUrlFetcher();

  SomeData FetchData(const URL &url, const UrlFetcher::ResponseCB &callback);

private:
  bool SsResponse_returnValue{false};
  char SsResponse_url[1024];

  void SsResponseCallback(const std::string &response);

  SomeServiceClient *ss_client_;
};

// ...

static const char ss_getlocalfile_uri[] = "bus://url_replace_service";

namespace net {

pthread_mutex_t g_url_change_callback_lock = PTHREAD_MUTEX_INITIALIZER;

SomeBusServiceClient::SomeBusServiceClient()
    : ss_client_(misc::BusServiceClient::PrivateBus) {}

SomeBusServiceClient::~SomeBusServiceClient() {}

bool SomeBusServiceClient::CallAsync(
    const std::string &uri, const std::string &param,
    const misc::BusServiceClient::ResponseCB &callback) {
  bool bRet;
  bRet = ss_client_.callASync(uri, param, callback);
  return bRet;
}

bool SomeBusServiceClient::CallSync(
    const std::string &uri, const std::string &param,
    const misc::BusServiceClient::ResponseCB &callback) {
  boold bRet bRet = false;
  int counter;

  pthread_mutex_lock(&g_url_change_callback_lock);
  ss_client_.callASync(uri, param, callback);

  counter = 0;
  for (;;) {
    int r = pthread_mutex_trylock(&g_url_change_callback_lock);
    if (r == 0) {
      bRet = true;
      pthread_mutex_unlock(&g_url_change_callback_lock);
    } else if (r == EBUSY) {
      usleep(kSleepMs);
      counter++;
      if (counter >= kSleepCountMax) {
        pthread_mutex_unlock(&g_url_change_callback_lock);
        break;
      } else
        continue;
    }
    break;
  }
  return bRet;
}

/**************************************************************************/

SpecificUrlFetcher::SpecificUrlFetcher() {}
SpecificUrlFetcher::~SpecificUrlFetcher() {}

void SpecificUrlFetcher::SsResponseCallback(const std::string &response) {
  std::unique_ptr<lib::Value> value(lib::JSONReader::Read(response));
  if (!value.get() || !value->is_dict()) {
    pthread_mutex_unlock(&g_url_change_callback_lock);
    return;
  }

  lib::DictionaryValue *response_data =
      static_cast<lib::DictionaryValue *>(value.get());
  bool returnValue;
  if (!response_data->GetBoolean("returnValue", &returnValue) || !returnValue) {
    pthread_mutex_unlock(&g_url_change_callback_lock);
    return;
  }

  std::string url;
  if (!response_data->GetString("url", &url)) {
    pthread_mutex_unlock(&g_url_change_callback_lock);
    return;
  }
  SsResponse_returnValue = true;

  size_t array_sz = arraysize(SsResponse_url);
  strncpy(SsResponse_url, url.c_str(), array_sz);
  SsResponse_url[array_sz - 1] = 0;

  pthread_mutex_unlock(&g_url_change_callback_lock);
}

SomeData SpecificUrlFetcher::FetchData(const URL &url,
                                       const UrlFetcher::ResponseCB &callback) {
  lib::DictionaryValue dictionary;
  std::string ss_request_payload;

  misc::BusServiceClient::ResponseCB response_cb =
      lib::Bind(&SpecificUrlFetcher::SsResponseCallback, this);

  SomeBusServiceClient *ss_client_ = new SomeBusServiceClient();

  dictionary.SetString("url", url.to_string());
  lib::JSONWriter::Write(dictionary, &ss_request_payload);

  SsResponse_returnValue = false;
  SsResponse_url[0] = 0x00;

  ss_client_->CallSync(ss_getlocalfile_uri, ss_request_payload, response_cb);
  URL new_url;
  if (SsResponse_returnValue) {
    new_url = URL::from_string(SsResponse_url);
  }

  delete ss_client_;
  return UrlFetcher::FetchData(new_url, callback);
}

} // namespace net
      
      



, , .





, .
  1. - UrlFetcher, , -- - - URL'. , - - , URL, URL, . Decorator.





  2. :





    1. ss_getlocalfile_uri - . ? .





    2. , . .





    3. , SsResponse_returnValue





    -:





    4. pthread-, std::thread, .





    5. - strncpy(); std::string - .





    6. ss_client_ . std::unique_ptr.





    7. usleep() - std::this_thread::sleep()





    :





    8. SomeBusServiceClient::CallSync kSleepMs kSleepCountMax, . .





    :





    9. message bus . . , message bus, - , kSleepCountMax*kSleepMs, , - ( callASync - id ?). - , , URL, .





    9. FetchData , new_url , .





    10. FetchUrl, , . , , -- WTF? ? , ?





    11. ( FetchUrl ), SsResponseCallback . , , . pthread undefined behavior.





    12. Nota valiosa de @snizovtsev : "... no puede usar esta primitiva de sincronizaci贸n para tal tarea. En caso de un tiempo de espera, el desbloqueo se llamar谩 2 veces. Es decir, el c贸digo es incorrecto a nivel de algoritmo y necesita para reescribir todo en una variable de condici贸n "





Las respuestas y comentarios del candidato nos permitieron hacernos una idea de su nivel de conocimiento de los est谩ndares y buenas pr谩cticas modernas de C ++, comprensi贸n de asincron铆a y multiproceso, meticulosidad en la revisi贸n y capacidad de "depurar" el c贸digo en su cabeza. Bueno, y establezca temas para una mayor conversaci贸n de coraz贸n a coraz贸n.








All Articles