ソフトウェア開発者の立場のための代替面接

ヤンデックスでのアルゴリズムパズルとインタビューについてここハブレで雷鳴の議論を背景に、あるかなり大きな(ロシア以外の)会社で働いている私の友人の一人が、彼らが行ったインタビューから私に問題を提供したことを思い出しました。今、問題は変わったので(彼らはコードのよりクールな例を見つけました)、彼の許可を得て、私はここに古いバージョンを公開します。





開発者の立場に来た候補者には、アルゴリズムの問​​題は与えられず、言語の荒野を駆け抜けることはなく、単にレビュー用のコードが与えられました。かつて1人のグリーンジュニアを凍結しようとした実際のプロジェクトのコード。幸いなことに、彼らは時間内にそれに気づきました。





次のことを行うことが提案されました。





  1. コードを調べて、一言で言えばそれが何をするのかを推測します。(すべてがプロジェクトでかなりよく文書化されていますが、文書化とコメントのあるサードパーティのライブラリは時々問題を抱えており、開発者はそこで何が起こっているのかを理解する必要があります)





  2. コードレビューを実施し、疑わしい場所と悪い場所を指摘し、それらを改善またはやり直す方法を提案します。あなたはどんな質問をしてもあなたが望むものは何でもグーグルすることができます。





コードはC ++ですが、バグのほとんどは他の言語の開発者でも見つけることができます。コードは次のようなものでした:





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. @snizovtsevからの貴重なメモ: "...このようなタスクにはこの同期プリミティブを使用できません。タイムアウトの場合、ロック解除が2回呼び出されます。つまり、コードがアルゴリズムレベルで正しくないため、必要です。すべてを条件変数に書き換える」





候補者からの回答とコメントにより、最新のC ++標準とグッドプラクティスに関する彼の知識レベル、非同期とマルチスレッドの理解、レビューの細心の注意、および彼のコードを「デバッグ」する機能についてのアイデアを得ることができました。頭。さて、そしてさらなる会話のためのトピックを心から心に設定します。








All Articles