четверг, 3 декабря 2009 г.

[comp.prog.flame] И еще одно сравнение C++ с Erlang (британскими учеными на этот раз)

На RSDN-е проскочила ссылка на очередное сравнение C++ и Erlang, на этот раз выполненное в Motorola Labs совместно с университетом Heriot-Watt из Эдинбурга. Вот презентация этого сравнения:

При просмотре презентации я обратил внимание на один подозрительный момент – там где идет сравнение объемов кода на слайде 27. Чтобы убедиться в их обоснованности, я нашел PDF-ку с описанием этой работы – вот она: High-Level Distribution for the Rapid Production of Robust Telecoms Software: Comparing C++ and Erlang. А вот эти фрагменты крупным планом. На erlang-е:

sz_dme_dmtx:cast(device_info)

И оригинальный фрагмент на C++, который, якобы, делает тоже самое:

void DataMobilityRxProcessor::processUnsupVer(void)
{
  MSG_PTR msg_buf_ptr;
  MM_DEVICE_INFO_MSG *msg_ptr;
  RETURN_STATUS ret_status;
  UINT16 msg_size;

  // Determine size of ici message
  msg_size = sizeof( MM_DEVICE_INFO_MSG);

  // Create ICI message object to send to DMTX so it sends a Device Info
  // message to Q1 and Q2 clients
  IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID, msg_size);

  // Retrieve ICI message buffer pointer
  msg_buf_ptr = ici_msg_object.getIciMsgBufPtr();

  // Typecast pointer from (void *) to (MM_DEVICE_INFO_MSG *)
  msg_ptr = (MM_DEVICE_INFO_MSG *)msg_buf_ptr;

  // Populate message buffer
  SET_MM_DEVICE_INFO_DEVICE_TYPE( msg_ptr, SERVER);
  SET_MM_DEVICE_INFO_NUM_VER_SUPPORTED( msg_ptr, NUM_VER_SUPPORTED);
  SET_MM_DEVICE_INFO_FIRST_SUP_PROTO_VERS( msg_ptr, PROTO_VERSION_ONE);

  // Send message to the DMTX task
  ret_status = m_ici_io_ptr->send(&ici_msg_object);

  // Check that message was sent successfully
  if (ret_status != SUCCESS)
  {
    // Report problem when sending ICI message
    sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__,
      "DataMobilityRxProcessor processUnsupVer: failure sending "
      " device info message to DMTX");

Оставим сейчас в стороне логическое соответствие этих двух фрагментов (действительно, пусть в Erlang программе сущность device_info сразу рождается полностью корректно сформированной и в C++ сделать тоже самое ну никак нельзя). Достаточно просто взглянуть на C++ный код и ужаснуться.

Даже не переделывая ничего в дизайне программы его можно (и нужно) очень сильно сократить. Ну хотя бы вот так:

void DataMobilityRxProcessor::processUnsupVer(void)
{
  // Create ICI message object to send to DMTX so it sends a Device Info
  // message to Q1 and Q2 clients
  IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID,
      sizeof( MM_DEVICE_INFO_MSG ) );

  // Retrieve ICI message buffer pointer and
  // Typecast pointer from (void *) to (MM_DEVICE_INFO_MSG *)
  MM_DEVICE_INFO_MSG * msg_ptr =
      (MM_DEVICE_INFO_MSG *)ici_msg_object.getIciMsgBufPtr();

  // Populate message buffer
  SET_MM_DEVICE_INFO_DEVICE_TYPE( msg_ptr, SERVER);
  SET_MM_DEVICE_INFO_NUM_VER_SUPPORTED( msg_ptr, NUM_VER_SUPPORTED);
  SET_MM_DEVICE_INFO_FIRST_SUP_PROTO_VERS( msg_ptr, PROTO_VERSION_ONE);

  // Send message to the DMTX task
  const RETURN_STATUS ret_status = m_ici_io_ptr->send(&ici_msg_object);

  // Check that message was sent successfully
  if (ret_status != SUCCESS)
  {
    // Report problem when sending ICI message
    sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__,
      "DataMobilityRxProcessor processUnsupVer: failure sending "
      " device info message to DMTX");

Уже получается 27 строк вместо 35 (сокращение на 22%, если пародировать подобные отчеты). А если поступить нормально и вынести все манипуляции с msg_ptr во вспомогательную функцию, то получится еще компактнее:

void DataMobilityRxProcessor::processUnsupVer(void)
{
  // Create ICI message object to send to DMTX so it sends a Device Info
  // message to Q1 and Q2 clients
  IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID,
      sizeof( MM_DEVICE_INFO_MSG ) );

  // Populate message buffer
  populateMessageBuffer(
      (MM_DEVICE_INFO_MSG *)ici_msg_object.getIciMsgBufPtr() );

  // Send message to the DMTX task
  const RETURN_STATUS ret_status = m_ici_io_ptr->send(&ici_msg_object);

  // Check that message was sent successfully
  if (ret_status != SUCCESS)
  {
    // Report problem when sending ICI message
    sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__,
      "DataMobilityRxProcessor processUnsupVer: failure sending "
      " device info message to DMTX");

Почти в два раза меньше исходного варианта. Я бы пошел еще дальше, и повыбрасывал бы эти дебильные комментарии вида “Ща мы проверим успешность операции”, да и количество пустых строк подсократил бы. Конечно, однострочного “аналога” на Erlang-е не получилось бы, но процентов из 60% от исходного индусокода можно было бы выбросить смело.

Резюмируя хочется сказать, что C++ далеко не самый лучший язык программирования, и наверняка системы для телекома лучше писать на Erlang-е. Но! Когда на Erlang-е начнут писать такие же горе-программисты, которые написали процитированный C++ный код, то все достоинства Erlang-а одним махом станут его недостатками.

Эдинбург находится в Великобритании ;)

Отправить комментарий